如何区分函数参数中的右值和右值引用 [英] How to distiguish between an rvalue and rvalue reference in a function parameter

查看:311
本文介绍了如何区分函数参数中的右值和右值引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

传递参数时,我想在函数参数中区分这两种情况,如下所示:

  int rvalue(); 
int&&& rvalue_ref();

f(rvalue());
f(rvalue_ref());但是,当我尝试转发这样的引用:


$ b

$ b

  int rvalue()
{
return 1;
}

int&& rvalue_ref(int i)
{
return std :: move(i);
}

template< class T>
void f(T& x)
{
if(std :: is_rvalue_reference< T>())
{
std :: cout< ; Rvalue reference<< std :: endl;
}
else if(std :: is_lvalue_reference< T>())
{
std :: cout< Lvalue reference<< std :: endl;
}
else
{
std :: cout< 不是参考<< std :: endl;
}
}

int main()
{
f(rvalue()); // should printNot a reference
f(rvalue_ref(1)); //应打印Rvalue reference
}

它打印出对于这两种情况。有没有办法在C ++中区分两种情况?

解决方案

我不知道如何单独使用函数参数。 xvalue和prvalue之间的区别可能会在函数调用中丢失。



但是你可以通过调用 decltype 对参数,在调用函数之前。这里有一个例子,调用你的函数,把相关信息作为第二个参数。我借用了此主题的代码。

  #include< iostream> 

int rvalue()
{
return 1;
}

int&& rvalue_ref(int&& i)//修改签名以避免返回引用局部变量(ty。user657267)
{
return std :: move(i);
}

template< typename T>
struct value_category {
//或者可以是一个积分或枚举值
static constexpr auto value =prvalue;
};

template< typename T>
struct value_category< T&> {
static constexpr auto value =lvalue;
};

template< typename T>
struct value_category< T&&> {
static constexpr auto value =xvalue;
};

//用于确保检查表达式的双括号,
//不是实体
#define VALUE_CATEGORY(expr)value_category< decltype((expr))> ::值

#define f(X)f_(X,VALUE_CATEGORY(X))

template< class T>
void f_(T&& x,char const * s)
{
std :: cout< s<< '\\\
';
}

int main()
{
f(rvalue()); // should printNot a reference
f(rvalue_ref(1)); //应该打印Rvalue reference
int j; f(j);
}

输出:

  prvalue 
xvalue
lvalue

当然,你可以修改字符串以适应,或者用枚举等替换它们。


When passed a parameter, I would like to distinguish between these two cases in a function parameter, like this:

int rvalue();
int&& rvalue_ref();

f(rvalue());
f(rvalue_ref());

However, when I try with forwarding references like this:

int rvalue()
{
    return 1;
}

int&& rvalue_ref(int i)
{
    return std::move(i);
}

template<class T>
void f(T&& x)
{
    if (std::is_rvalue_reference<T>())
    {
        std::cout << "Rvalue reference" << std::endl;
    }
    else if (std::is_lvalue_reference<T>())
    {
        std::cout << "Lvalue reference" << std::endl;
    }
    else
    {
        std::cout << "Not a reference" << std::endl;
    }
}

int main() 
{
    f(rvalue()); // Should print "Not a reference"
    f(rvalue_ref(1)); // Should print "Rvalue reference"
}

It prints out "Not a reference" for both cases. Is there a way to distinguish both cases in C++?

解决方案

I don't see how to do this solely using function parameter. The distinction between xvalue and prvalue may be lost in the function call.

But you can do it with a macro that calls decltype on the argument, before calling the function. Here is an example that calls your function with the relevant information as a second parameter. I borrowed code from this thread.

#include <iostream>

int rvalue()
{
    return 1;
}

int&& rvalue_ref(int &&i)   // Modified signature to avoid return reference to local variable (ty. user657267)
{
    return std::move(i);
}

template<typename T>
struct value_category {
    // Or can be an integral or enum value
    static constexpr auto value = "prvalue";
};

template<typename T>
struct value_category<T&> {
    static constexpr auto value = "lvalue";
};

template<typename T>
struct value_category<T&&> {
    static constexpr auto value = "xvalue";
};

// Double parens for ensuring we inspect an expression,
// not an entity
#define VALUE_CATEGORY(expr) value_category<decltype((expr))>::value

#define f(X) f_(X, VALUE_CATEGORY(X)) 

template<class T>
void f_(T&& x, char const *s)
{
    std::cout << s << '\n';
}

int main() 
{
    f(rvalue()); // Should print "Not a reference"
    f(rvalue_ref(1)); // Should print "Rvalue reference"
    int j; f(j);
}

Output:

prvalue
xvalue
lvalue

Of course you can trivially modify the strings to suit, or replace them with enums etc.

这篇关于如何区分函数参数中的右值和右值引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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