2016-04-27 4 views
1

Я понятия не имею, почему компилятор дает мне предупреждения о экземплярах шаблонов.std :: forward с templated overloaded function

То есть кусок кода, который работает просто отлично, и выводит Lvalue/RValue правильно:

//template<typename T> 
void overloaded(const /*T*/std::string& in) 
{ 
    std::cout << "lvalue" << std::endl; 
} 

//template<typename T> 
void overloaded(/*T*/std::string&& in) 
{ 
    std::cout << "rvalue" << std::endl; 
} 

template<typename T> 
void pass(T&& in) 
{ 
    overloaded(std::forward<T>(in)); 
} 

int main() 
{ 
    std::string a; 
    pass(a); 
    pass(std::move(a)); 
    getchar(); 
} 

Но мне нужно, чтобы использовать его с шаблонного типа. Так изменения «перегруженные» функции

template<typename T> 
void overloaded(const T& in) 
{ 
    std::cout << "lvalue" << std::endl; 
} 

template<typename T> 
void overloaded(T&& in) 
{ 
    std::cout << "rvalue" << std::endl; 
} 

дает шаблон Instantiations предупреждения, (когда мне его ясно T должен быть StD :: string), и консоль выводит RValue 2 раза вместо Lvalue первого.

Что я делаю неправильно?

+0

Работы для меня. http://coliru.stacked-crooked.com/a/fc00c140c9a8e208 – erip

+0

'T &&' является ссылкой для пересылки, т. е. если 'T' является параметром шаблона типа, он больше не является регулярной ссылкой на rvalue –

ответ

1

Шаблоны, такие как T&& являются специальными. Они называются «справочными ссылками». У них есть специальные правила дедукции для функций, таких как:

template<typename T> 
void overloaded(T&& in) 

Предположим на минуту, что overloaded не перегруженный. Если вы передадите выражение lvalue типа std::string на overloaded, T будет выводиться как std::string&. Если вы передадите выражение rvalue типа std::string на overloaded, T выведет на std::string. Вы можете использовать эти знания, чтобы сделать это:

template<typename T> 
void overloaded(T&& in) 
{ 
    if (std::is_lvalue_reference<T>::value) 
     std::cout << "lvalue" << std::endl; 
    else 
     std::cout << "rvalue" << std::endl; 
} 

В общем, это анти-паттерн перегружать T&& шаблоны с что-нибудь еще. Эти специальные шаблоны пригождаются, когда вы хотите все поймать.

+0

Wow i был совершенно не осведомлен того, что! Благодаря! – Pancake

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