问题描述
我无法重载函数,以通过const引用或如果它是一个右值,一个右值引用获取一个值。问题是我的非常量值绑定到函数的右值版本。我在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> & >(向量< int>&& t)
foo< vector< int> >(const vector< int>& t)
void foo(typename remove_reference< T> :: type&& t)
但这只会导致一切都解析为const-lvalue引用版本。
如何防止此行为?为什么这是默认的 - 似乎很危险,因为右值引用允许被修改,这使我有一个意想不到的修改局部变量。
编辑:只是添加了非模板版本的函数,它们按预期工作。使函数作为模板更改过载分辨率规则?这是非常令人沮丧的!
void bar(const vector< int>& t)
{cout ;& void bar(const vector< int>&)< endb;}
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>&&)
解决方案当您有这样的模板化函数时,您几乎从不想要重载。
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<< 易失性;
std :: cout<< typeid(Trcv).name();
if(is_lvalue_reference< T> :: value)
std :: cout< '&';
else if(is_rvalue_reference< T> :: value)
std :: cout<< &&;
std :: cout<< '\\\
';
}
template< class T>
void foo(T& t)
{
display< T>();
}
int main()
{
vector< int> X;
vector< int> const cx;
foo(x); // vector< int>&
foo(vector foo(cx); // const vector< int>&
}
I'm having trouble overloading a function to take a value either by const reference or, if it is an rvalue, an rvalue reference. The problem is that my non-const lvalues are binding to the rvalue version of the function. I'm doing this in 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&&) }
The priority seems to be to deduce foo(x) as
foo< vector<int> & >(vector<int>& && t)
instead of
foo< vector<int> >(const vector<int>& t)
I tried replacing the rvalue-reference version with
void foo(typename remove_reference<T>::type&& t)
but this only had the effect of causing everything to resolve to the const-lvalue reference version.
How do I prevent this behaviour? And why is this the default anyway - it seems so dangerous given that rvalue-references are allowed to be modified, this leaves me with an unexpectedly modified local variable.
EDIT: Just added non-template versions of the functions, and they work as expected. Making the function a template changes the overload resolution rules? That is .. really frustrating!
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>&&)
解决方案When you have a templated function like this you almost never want to overload. The
T&&
parameter is a catch anything parameter. And you can use it to get any behavior you want out of one overload.#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>& }
这篇关于防止非const值从解析到右值引用,而不是const lvalue引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!