T&& в шаблонной функции и классе

Я только что наткнулся на это T&& в классе и функции означает разные вещи.
В функции:

template<class T> void f(T&& t){};   // t is R or L-value
...
int i=0; 
f(i);   // t in f is lvalue
f(42);  // t in f is rvalue  

В классе:

template<class T> 
struct S { 
       S(T&& t){}  // t is only R-value? 
};
...
int i;
S<int> ss(i);   // compile error - cannot bind lvalue to ‘int&&’

Означает ли это, что если у нас естьT&& t в классе, чем t будет только рвалуе?
Кто-нибудь может указать мне, где я могу получить больше информации об этом?
Означает ли это, что мне нужно написать две перегрузки метода для L и R-значений?

ОТВЕТ
Как показывает пример Альфа, t в функции и классе может быть Lvalue или Rvalue.

2 ответа

Решение

В вашей функции T выводится из фактического аргумента. Основное применение этой конкретной комбинации - идеальная пересылка. В шаблоне класса T не выводится, оно должно быть указано.

Например, это прекрасно компилируется как с g++, так и с msvc:

template<class T> 
struct S { 
       S(T&& t){}
};

int main()
{
    int i;
    S< int& > ss(i);
}

Вы имеете дело с выводом аргументов шаблона здесь.

Используя f без явного определения аргумента шаблона, компиляторы C++ теперь должны решить, какой тип аргумента шаблона T от параметров вы передаете его.

Правила вывода аргументов шаблона с && типы являются специальными, чтобы обеспечить идеальную пересылку. Когда вы используете f(i), T выводится как T&, Таким образом, параметр t имеет тип T& &&, который падает до T&, Тем не менее, когда вы используете f(42)тип T выводится как T&&, и поэтому t является T&& &&, который падает до T&&,

Когда вы заставляете T чтобы быть конкретным типом, все, что эффективно уходит. Разрушение все еще может произойти, но потому что вы использовали S<int>, затем t будет иметь тип int&&, S<int> ss(i) фактически является эквивалентом f<int>(i), что тоже не законно. А так как вывод аргументов шаблона работает только с функциями, а не с типами, вы должны сделать что-то подобное для S если вы хотите совершенную пересылку:

template<class T> 
struct S { 
    template<class U>
    S(U&& t){}
};

Конечно, вы можете использовать методы SFINAE и метапрограммирование шаблона, чтобы гарантировать, что шаблон конструктора может быть создан только в том случае, если базовый тип T а также U подобные.

Другие вопросы по тегам