2016-03-17 5 views
1

Когда передается параметр, я хотел бы провести различие между этими двумя случаями в качестве параметра функции, например:Как distiguish между RValue и RValue ссылки в качестве параметра функции

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

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

Однако, когда я пытаюсь с переадресацией таких ссылок:

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" 
} 

В обоих случаях печатается «Не ссылка». Есть ли способ отличить оба случая от C++?

+5

Почему вы хотите отличить эти два случая в первую очередь? –

+1

Вы, похоже, действительно задаетесь вопросом, как вести себя по-разному для аргумента xvalue, чем аргумент prvalue –

+1

Ха-ха, я вызвал внутреннюю ошибку компилятора в g ++ 5.2 при попытке чего-то –

ответ

3

Я не вижу, как это можно использовать исключительно с помощью параметра функции. Различие между значениями x и prvalue может быть потеряно в вызове функции.

Но вы можете сделать это с помощью макроса, который вызывает аргумент decltype, прежде чем вызывать функцию. Вот пример, который вызывает вашу функцию с соответствующей информацией в качестве второго параметра. Я позаимствовал код у 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); 
} 

Выход:

prvalue 
xvalue 
lvalue 

Конечно, вы можете тривиальное изменить строки в костюм, или заменить их перечисления и т.д.

+0

Означает ли это значение lvalue и prvalue? –

+0

Добавленный пример @NickyC –

0

Причины, почему ваш код сказал: «Не ссылка» является что вы прошли T по std::std::is_lvalue_reference<> и std::std::is_rvalue_reference<>. Вы должны использовать decltype(), чтобы получить его оригинальный тип.

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

Это выводит «Rvalue reference» дважды для меня. Вы попробовали? (Если вы получите разные результаты, отправьте MCVE, так как это означает, что у одного из нас есть испуганный компилятор) –

+0

Возможно, если вы попробуете 'decltype (std: forward (x))'? – KABoissonneault

+0

, потому что все в ravlue в тестовом примере выше;) – robotician

Смежные вопросы