防止非const值从解析到右值引用,而不是const lvalue引用 [英] Preventing non-const lvalues from resolving to rvalue reference instead of const lvalue reference

查看:143
本文介绍了防止非const值从解析到右值引用,而不是const lvalue引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法重载函数,以通过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引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆