Временные значения C ++ в шаблоне - PullRequest
8 голосов
/ 08 июня 2010

Можете ли вы объяснить мне разницу между механизмом следующего:

int function();

template<class T>
void function2(T&);

void main() {
    function2(function()); // compiler error, instantiated as int &

    const int& v = function();
    function2(v); // okay, instantiated as const int&
}

Правильно ли мое рассуждение в отношении инстанцирования? почему сначала не создается экземпляр const T&?

Спасибо

Ответы [ 4 ]

3 голосов
/ 08 июня 2010

Потому что function возвращает неконстантное значение. Только объекты могут быть const, потому что они хранят некоторое состояние, которое можно изменить, если оно не является const. То, что вы возвращаете, это не объект, а чистая ценность. Концептуально они не модифицируемы (как, например, константы перечисления), но они не являются константными (как, опять же, константы перечисления).

2 голосов
/ 08 июня 2010

Я думаю, что вы можете быть запутаны между rvalues ​​и квалификатором const. function возвращает неконстантное временное значение типа int, поэтому компилятор выводит T как int, как и должно быть. Как вы указали, вы можете привязать временное к const ref (c ++ 03 12.2 / 5), но компилятор не будет добавлять квалификаторы cv, чтобы сделать вызов функции правильно сформированным. Поскольку вы не можете управлять функцией шаблона, есть два пути решения этой проблемы (в дополнение к опубликованному вами решению).

(1) Явные параметры шаблона: function2<const int>(function())

(2) квалификационный возврат: const int function();

Оба эти решения хорошо сформированы. (1) кажется лучшим решением, ИМХО, поскольку (2) нетрадиционно и глупо.

Редактировать: На самом деле, выводимый тип может быть более квалифицированным по cv, чем аргумент для аргумента шаблона ref, но только в том случае, если в противном случае вывод типа завершится неудачей (c ++ 03 14.8.2.1/3). В этом случае дедукция типа не дает сбоя, но приводит к неправильному вызову функции (SFINAE не применяется, поскольку специализация шаблонной функции сама по себе не деформирована).

Если цель автора шаблона заключалась в том, чтобы не изменять аргумент, он должен быть объявлен как ссылочный аргумент const, так что это может быть ошибкой в ​​библиотеке шаблонов, или это может изменить аргумент, и в этом случае вы выполнение не удастся, когда функция попытается изменить аргумент.

Редактировать: Как указывает FredOverflow, не-классные значения всегда cv безоговорочно соответствуют стандарту 3.10 / 9. Итак, (2), который работает в gcc 4.3, на самом деле является ошибкой компилятора (gcc <4.5, согласно FredOverflow). </p>

0 голосов
/ 08 июня 2010

Чтобы скомпилировать первый вызов, необходимо определить функцию 2 с параметром T && - это rvalue, ссылка на временный объект.Во втором вызове v - ссылка lvalue, все в порядке.Если ваш компилятор не поддерживает ссылки rvalue, первый вызов может быть скомпилирован только с параметром T, без ссылки.

0 голосов
/ 08 июня 2010

В этой строке

function2(function()); 

после того, как функция 2 вернется, передаваемый ей аргумент может изменить свое значение, но поскольку функция () возвращается и она просто назначается временной переменной, но что произойдет с этой временной переменной после выхода из области видимости, так это проблема, поэтому жалобы компилятора.

...