Почему выведение аргументов не допускается в типе возвращаемого значения функции?
Самый очевидный ответ может быть - потому что стандарт говорит так.
Это нормально, но я оборачиваюсь вокруг этого, чтобы понять причины этого выбора.
Рассмотрим следующий пример:
template<typename T>
struct S { S(T) {} };
S f() { return 0; }
int main() {
auto s = f();
(void)s;
}
Он не компилируется с ошибками, такими как:
ошибка: использование шаблона класса 'S' требует аргументов шаблона; вычет аргумента не допускается в типе возврата функции
Довольно легко исправить, это не проблема, что-то вроде этого работает просто отлично:
auto f() { return S{0}; }
Тем не менее, я хотел бы понять, каковы были недостатки в разрешении вывода аргументов шаблона класса также в типах возвращаемых функций.
На первый взгляд, это выглядит как глупое ограничение, но я уверен, что упускаю что-то важное здесь.
3 ответа
Здесь нет ничего языкового закона: если указать тип возврата (а не auto
или же T
где T
является типом шаблона), этот возвращаемый тип должен быть действительным. позвольте мне привести еще более простой и лучший пример:
std::vector function() {
return std::vector<int>();
}
Очевидно, что он не компилируется, даже без модных шаблонов, auto
и введите вычеты, потому что std::vector
не тип, std::vector<int>
является.
Когда вы указываете S
в качестве типа возврата вы в основном
- Запретить компилятору выводить сам тип
- Укажите неверный тип возврата, как
S
не тип,S<int>
является.
Почему выведение аргументов не допускается в типе возвращаемого значения функции?
Потому что стандарт так говорит.
Вы можете задать вопрос: почему есть разница между этими строками кода:
S s = 0; // OK
S s() { return 0; } // error - even though this is also copy-initializing an "S" from 0
Вы можете придумать подробное объяснение того, почему первый должен быть в порядке, а второй - нет, но по сути было предложено вывести аргументы шаблона класса для рассмотрения только первого случая, а не второго. Первый из них в порядке, потому что стандарт говорит об этом, а второй - ошибка, потому что стандарт говорит об этом.
Предлагается расширение ( P1021, в разделе " Вывод типа возврата для функций"), которое будет касаться второго случая. Считаете ли вы это хорошей идеей... ¯\_(ツ)_/¯
Просто мои волнистые два цента, которые обобщают мое понимание:
В
S f() { return 0; }
S
это не тип, который можно вывести, это просто шаблон. Вы могли бы написать
template<typename T>
S<T> f() { return 0;}
но теперь очевидно, что для звонка
auto s = f();
нет никакого способа определить, какой тип T
должен быть.