выведение ссылок на const из аргументов rvalue - PullRequest
10 голосов
/ 20 мая 2011

Хорошо, это может показаться глупым вопросом, но здесь он звучит так:

template <typename T>
void foo(T& x)
{
}

int main()
{
    foo(42);
    // error in passing argument 1 of 'void foo(T&) [with T = int]'
}

Что мешает C ++ создать экземпляр шаблона функции foo с помощью T = const int вместо этого?

Ответы [ 3 ]

8 голосов
/ 20 мая 2011

Проблема состоит в том, что вычитание типа шаблона должно определять точное соответствие, и в этом конкретном случае из-за ссылки в сигнатуре точное соответствие требует lvalue. Значение 42 не является lvalue, а скорее rvalue, и разрешение T с помощью const int не даст идеального совпадения. Поскольку вычитание типа шаблона ограничено точными совпадениями, такое удержание не допускается.

Если вместо использования литерала вы используете неизменяемое значение lvalue, то компилятор определит тип соответствующим образом, так как const int станет идеальным соответствием для аргумента:

const int k = 10;
foo( k );            // foo<const int>( const int & ) is a perfect match

Теперь существует специальное правило, которое позволяет вызывать функцию, которая принимает константную ссылку (не изменяемое значение lvalue) со значением rvalue, что подразумевает создание временного значения lvalue, которое позднее привязывается к ссылке, но для этого правила необходимо включить функция должна иметь эту подпись перед этим, поэтому явно указывается, что тип шаблона const int работает: foo<const int>(42).

1 голос
/ 20 мая 2011

Это правила ;-). Если вы оставите компилятор для вывода типа из аргумента, он выберет самое простое, что может.

Это не кажется мне необоснованным. Ваш шаблон говорит, что ожидает неконстантную ссылку, поэтому он не компилируется с rvalue.

Вы можете либо сказать, что вы имеете в виду на сайте вызова: foo<int const>(42);, либо изменить свой шаблон, чтобы было ясно, что для него не нужна изменяемая ссылка: template <typename T> void foo(T const & x) { }.

В C ++ 11 у вас есть больше возможностей для выражения того, что ваш шаблон будет и не будет принимать.

0 голосов
/ 20 мая 2011

Будь то шаблон или обычные функции, значение не может быть передано по ссылке .(так что const T& работает, но не T&).

What is preventing C++ to instantiate the foo function template with T = const int instead?

Предположим, C ++ разрешает и делает T = const int вместо этого.Теперь через некоторое время вы измените foo на

template<typename T>
void foo (T& x)
{
  x = 0;
}

Теперь компилятор должен выдать ошибку .Для конечного пользователя опыт будет странным, так как для правильного утверждения типа x = 0; он начал выдавать ошибку.Это может быть причиной того, что компилятор предотвращает на первом этапе сам!

...