我在重载一个函数时遇到了问题,通过常量引用来获取一个值,或者如果它是一个右值,那么它就是一个右值引用。问题是我的非常量左值绑定到函数的右值版本。我在VC2010中做这件事。
#include <iostream>
#include <vector>
using namespace std;
template <class T>
void foo(const T& t)
{cout << "void foo(const T&)" << endl;}
template <class T>
void foo(T&& t)
{cout << "void foo(T&&)" << endl;}
int main()
{
vector<int> x;
foo(x); // void foo(T&&) ?????
foo(vector<int>()); // void foo(T&&)
}优先级似乎是将foo(x)推导为
foo< vector<int> & >(vector<int>& && t)而不是
foo< vector<int> >(const vector<int>& t)我尝试将rvalue-reference版本替换为
void foo(typename remove_reference<T>::type&& t)但这只会导致一切都解析到const-lvalue参考版本。
我如何防止这种行为?为什么这是默认的--鉴于允许修改右值引用,这似乎很危险,这给我留下了一个意外修改的局部变量。
编辑:只是添加了函数的非模板版本,它们可以正常工作。使函数成为模板会改变重载解决规则吗?那是..。真的很令人沮丧!
void bar(const vector<int>& t)
{cout << "void bar(const vector<int>&)" << endl;}
void bar(vector<int>&& t)
{cout << "void bar(vector<int>&&)" << endl;}
bar(x); // void bar(const vector<int>&)
bar(vector<int>()); // void bar(vector<int>&&)发布于 2011-10-13 08:55:22
当你有一个像这样的模板化函数时,你几乎不会,想要重载。T&&参数是一个catch anything参数。您可以使用它从一个重载中获得您想要的任何行为。
#include <iostream>
#include <vector>
using namespace std;
template <class T>
void display()
{
typedef typename remove_reference<T>::type Tr;
typedef typename remove_cv<Tr>::type Trcv;
if (is_const<Tr>::value)
cout << "const ";
if (is_volatile<Tr>::value)
cout << "volatile ";
std::cout << typeid(Trcv).name();
if (is_lvalue_reference<T>::value)
std::cout << '&';
else if (is_rvalue_reference<T>::value)
std::cout << "&&";
std::cout << '\n';
}
template <class T>
void foo(T&& t)
{
display<T>();
}
int main()
{
vector<int> x;
vector<int> const cx;
foo(x); // vector<int>&
foo(vector<int>()); // vector<int>
foo(cx); // const vector<int>&
}发布于 2011-10-13 08:36:20
为了使T&&绑定到左值引用,T本身必须是左值引用类型。您可以禁止使用引用类型T实例化模板
template <typename T>
typename std::enable_if<!std::is_reference<T>::value>::type foo(T&& t)
{
cout << "void foo(T&&)" << endl;
}enable_if在<utility>中;is_reference在<type_traits>中。
重载获取T&&优于重载获取T const&的原因是,T&&是完全匹配的(具有T = vector<int>&),但T const&需要限定转换(必须添加常量限定)。
这只会发生在模板上。如果您有一个接受std::vector<int>&&参数的非模板函数,则只能使用rvalue参数调用该函数。当您有一个采用T&&的模板时,您不应该将其视为“右值引用参数”;它是一个“通用引用参数”(我相信Scott Meyer使用了类似的语言)。它可以接受任何东西。
允许函数模板的T&&参数绑定到任何类型的参数是实现完美转发的原因。
https://stackoverflow.com/questions/7748104
复制相似问题