c++ - 在模板类中使用 r 和 l 值构造函数时出错

标签 c++ templates c++11 constructor overloading

我有一个这样的类模板:

template <typename T>
class MyClass
{
public:
     MyClass(const T & val);  // First
     MyClass(T&& val);        // Second
};

基本上我希望 MyClass 可以从 T 构造,无论它是右值还是左值。现在当我有类似的东西时

const A& foo = ...;
MyClass<const A&> x(foo); 

我得到 MyClass(const A & val) 的重定义错误。

我认为这是因为 T&& 是一个通用引用,并且由于引用折叠规则,第二个构造函数也被转换为具有与第一个相同的签名。

首先,我对错误场景的理解是否正确?其次,我该如何解决这个问题(我希望能够在构造 MyClass 时使用移动语义提供的优化)?

最佳答案

I presume this is because T&& is a universal reference ...

不正确。 T&& 在这种情况下不是通用(转发)引用。 T&& 恰好是对 T 的右值引用。必须推导出通用/转发引用。

... and due to reference collapsing rules, the second constructor also gets converted to having the same signature as the first.

这是是正确的。我们的两个构造函数采用:

T const& ==> A const& const& ==> A const&
T&&      ==> A const& &&     ==> A const&

因此出现重定义错误。

根据您要执行的操作,一个简单的解决方案可能是 std::decay T:

template <typename T>
class MyClass
{
    using DecT = typename std::decay<T>::type;

public:
    MyClass(const DecT& );
    MyClass(DecT&& );
};

对于您的示例,这仍然会创建一个具有两个构造函数的类:一个采用 const A&,另一个采用 A&&

关于c++ - 在模板类中使用 r 和 l 值构造函数时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28286546/

相关文章:

c++ - 类定义中定义的成员函数的编译方式是否与 C++ 中其他地方定义的成员函数不同?

multithreading - C++中的多线程生产者/消费者

c++ - 在 C++ 中为代码执行添加延迟

c++ - 打印多种不同类型的数字限制

c++ - 如果我在 C++ 中使用内联函数,为什么会重新定义“template<class T>”?

c++ - 为什么 C++ 不允许将 void 参数传递给具有零参数的函数?

c++ - `auto x = f()` 比 `T x = f()` 好吗?

C++ : calling the right method of a derived class according to the types of the arguments

c++ - std::thread 在使用参数创建时抛出访问冲突异常?

c++ - 如何卸载托管的c++ dll?