让我们考虑一个简单的类右值引用和构造函数参数
template< typename T >
class Wrapper {
public:
// Constructors?
private:
T wrapped;
};
它应该使用什么样的构造是有效的?
C++之前0X会有一个构造函数之一:
- const引用(
T const&
) - 如果类型是T
“重”, - 或值(
T
) - 如果类型T
是“轻”。
确定类型T
是“重”还是“轻”并不容易。
人们可以假设只有内建类型(int/floats/...)是“轻”。但这并不完全正确,因为我们自己的Wrapper<int>
最有可能也应该被视为“轻”类型。
像boost::call_traits
这样的库提供了一些手段,通过允许类型创建者将类型标记为“轻”(通过提供适当的call_traits
专业化)来克服此困难。否则它将被视为“重”。似乎可以接受。
但是,C++ 0x使情况变得更糟。因为现在你也有参考(T&&
),它允许有效地采取(一些)“重”的对象。
因为这个现在你必须之中选择和:
- 只是const引用(
T const&
) - 如果类型T
是“重”,不支持移动语义(因为无论有没有 - 像大荚 - 或没有写,你有没有影响), - 两个const引用(
T const&
)和右值引用(T&&
) - 如果类型T
是“重”,不支持移动语义, - 只值(
T
) - 如果T
类型是“轻量级”或者是“重量级”但支持移动语义(即使进行了复制,也不会打扰使用,否则我们不得不自己复制T const&
...)。
还不容易分辨哪些类型是“重”,哪些类型是“轻”(如以前)。但是现在你也不知道类型T
是否支持移动语义(或者你是否?)。
一旦你换一个以上的值,因为可能的构造函数重载数量呈指数级增长,这变得更加恼人。
有没有解决这个问题的方法?
我虽然关于转发(完美转发)参数的一些模板构造函数,但我不确定是否会按需要工作。而且它还允许提供将被转发给T
构造函数的不同类型的值。这可能被认为是一个功能,但不一定。
您也可以使用具有相同完美转发的可变参数构造函数来构造'value'。您只需编写一个通用构造函数:'template Wrapper(U && ... us):value(std :: forward (us)...){} –
2012-07-20 11:29:43
@AlexandreC:是是的,已经在那:-) – 2012-07-20 11:30:02
只有一个问题:'std :: enable_if'在这里并不是必须的(它不会改善错误报告)。这里有什么用处? – 2012-07-20 11:32:36