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 &&数据):数据(std :: move(数据)){
但是,当我调用make_message(1024)
和make_message(std::move(a))
时,它起作用。
那么为什么当T = int&时构造函数Message(const T& data)
与Message(T&& data)
重复?
那么为什么当T = int&时构造函数Message(const T&data)与Message(T && data)重复?
由于参考折叠规则。
没有引用作为参考。当T
是左值引用时-假设int &
,那么从语法上讲T &
似乎是int & &
。但是这种类型不存在。语言规则说,在这种情况下,T &
会折叠为int &
。
类似地,没有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
也一样。