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)
是重复的?
答案 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
,其中T
是const int
,则它会折叠成const int
。 volatile
也是如此。