Предаване на Lvalue към параметър на RValue

Исках да знам как е възможно това?

template<typename T>
void Test(T&& arg)
{
    arg = 14;
}


int a = 23;
Test(a);

Въпросът ми е, че функцията Test изисква аргумент от тип Rvalue, но изглежда, че приема и параметър от тип lvalue. Защо така ? Дали това се дължи на наличието на шаблони? Защото, ако направя нещо подобно

void AnotherTest(int&& arg)
{
    arg = 14;
}

Тогава функцията изисква параметърът да е от тип Rvalue. Ще съм благодарен, ако някой може да обясни защо наличието на шаблони променя поведението.


person Rajeshwar    schedule 11.05.2014    source източник
comment
Потърсете свиващи се и универсални препратки.   -  person juanchopanza    schedule 12.05.2014
comment
T&& не е rvalue-reference (докато int&& е). Тя ще бъде изведена до rvalue- или lvalue-reference, в зависимост от категорията на стойността на аргументния израз. Скот Майерс го нарича универсална справка.   -  person jrok    schedule 12.05.2014
comment
@jrok: Приблизително, но не съвсем правилно. Аргументите на шаблона са изведени, а не параметрите на функцията на шаблона. Тогава типът за аргумента ще бъде rvalue-reference към извлечения тип, който в крайна сметка може да бъде аргумент lvalue-reference.   -  person David Rodríguez - dribeas    schedule 12.05.2014


Отговори (1)


Ключът, както правилно си представяте, е, че това е шаблон и че типът аргумент се извежда. Когато извикате Test с lvalue, правилата за дедукция на тип аргумент когато аргументът е rvalue-reference ще изведат типа T като lvalue-reference и по този начин специализацията става:

template <>
void Test<int&>(int & && arg)

В този момент влизат в сила правилата за свиване на препратки и типът на аргумента става:

template <>
void Test<int&>(int & arg)

Въпреки че шаблонът приема rvalue-reference, ако типът е lvalue-reference, аргументът се превръща в lvalue-reference.

person David Rodríguez - dribeas    schedule 11.05.2014