【问题标题】:Why constructor Message(const T& data) is conflict with Message(T&& data) when T = int&?为什么当 T = int& 时构造函数 Message(const T& data) 与 Message(T&& data) 冲突?
【发布时间】:2019-12-25 03:29:37
【问题描述】:
template <typename T>
struct Message {
    T data;
    explicit Message(T&& data) : data(std::move(data)) {
        std::cout << "Move data" << std::endl;
    }

    explicit Message(const T& data) : data(data) {
        std::cout << "Copy data" << std::endl;
    }
};

template <typename T>
inline Message<T>*
makeMessage(T&& data) {
    return new Message<T>{std::forward<T>(data)};
}


int main() {
    const int a = 1024;
    auto *copy_msg = makeMessage(a);
}

有一个模板类Message 有两个构造函数:Message(T&amp;&amp; data)Message(const T&amp; data),当我调用makeMessage(a) 时出现以下编译时错误。

错误:'Message' 的多个重载实例化为相同的签名 'void (const int &&)'

显式消息(常量 T& 数据):数据(数据){

之前的声明在这里

显式消息(T&& 数据) : data(std::move(data)) {

但是,当我调用 make_message(1024)make_message(std::move(a)) 时,它可以工作。

那么为什么当 T = int& 时构造函数 Message(const T&amp; data)Message(T&amp;&amp; data) 重复?

【问题讨论】:

  • 在您的示例中,Tconst int&amp;,而不是 int&amp;
  • @eerorika 当Tint&amp; 时,错误是一样的。

标签: c++ c++11 compiler-errors move-semantics overload-resolution


【解决方案1】:

那么为什么当 T = int& 时构造函数 Message(const T& data) 与 Message(T&& data) 重复?

因为参考折叠规则。

没有引用引用这样的东西。当T 是一个左值引用时——比如说int &amp;,那么在语法上T &amp; 似乎是一个int &amp; &amp;。但这种类型不存在。语言规则说,在这种情况下,T &amp; 会折叠成int &amp;

同样,没有 const 引用(不要与 const 引用混淆,人们有时说 const 引用时的意思)。当T 是左值引用时——假设int&amp;,那么在语法上T const(与const T 相同)似乎是int&amp; const(不要与int const &amp; 混淆,后者与@987654333 相同@)。但这种类型不存在。语言规则说,在这种情况下,T const 会折叠成int &amp;

C++11 引入了右值引用,为我们带来了新的折叠规则。简而言之,“对右值引用的右值引用”折叠为右值引用,但“对任何引用的左值引用”以及“对左值引用的任何引用”折叠为左值引用。这条规则是转发引用工作原理的一部分。

因此,给定T = int &amp;,它们声明了相同的函数:

explicit Message(T&& data)      // type of argument is int &
explicit Message(const T& data) // type of argument is int &

奖励:非引用也有折叠规则:没有 const const 类型这样的东西。因此,给定const T,其中Tconst int,然后它会折叠成const intvolatile 也是如此。

【讨论】:

  • 所以这意味着我在声明make_message(a) 中实例化了一个类Message&lt;int&amp;&gt; 而不是Message&lt;int&gt; ---> new Message&lt;T&gt;{std::forward&lt;T&gt;(data)};?
  • @daoliker,你实例化了Message&lt;const int&amp;&gt;
猜你喜欢
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 2012-01-21
  • 2012-08-02
相关资源
最近更新 更多