当T = int&时,为什么构造函数Message(const T && data)与Message(T && data)冲突?

时间:2019-12-25 03:29:37

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

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&& data)Message(const T& data),当我调用makeMessage(a)时遇到了以下编译时错误。

  

错误:“消息”的多个重载实例化到相同的签名“ void(const int &&)”

     
    

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

  
     

先前的声明在这里

     
    

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

  

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

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

1 个答案:

答案 0 :(得分:4)

  

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

由于引用折叠规则。

没有引用作为参考。当T是左值引用时-假设int &,那么在语法上T &似乎是int & &。但是这种类型不存在。语言规则规定,在这种情况下,T &会折叠成int &

类似地,没有const引用之类的东西(不要与const的引用混淆,人们在说const引用时有时会指的是const引用)。当T是左值引用时-假设int&,则在语法上T const(与const T一样)似乎是int& const(不要与int const &,与const int &相同)。但是这种类型不存在。语言规则规定,在这种情况下,T const会折叠成int &

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

因此,给定T = int &,它们声明了相同的功能:

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

奖金:对于非引用也有崩溃的规则:没有const const type这样的东西。这样,给定const T,其中Tconst int,则它会折叠成const intvolatile也是如此。