Почему выведение аргументов не допускается в типе возвращаемого значения функции?

Самый очевидный ответ может быть - потому что стандарт говорит так.
Это нормально, но я оборачиваюсь вокруг этого, чтобы понять причины этого выбора.

Рассмотрим следующий пример:

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 должен быть.

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