Почему нельзя возвращать тип возврата?
Как и ожидалось, в С++ 11 происходит сбой: поскольку этот язык не имеет вывода типа возврата для стандартных функций болота:
auto main()
{
return 0;
}
Однако С++ 14, поэтому я не могу объяснить следующую ошибку (с эквивалентными результатами в соединительной линии GCC, clang 3.8 и Visual Studio 2015):
error: 'main' must return 'int'
Есть ли проход в стандарте, который я не вижу, запрещающий вывод типа возврата для main
? Или оба компилятора несовместимы?
(Для чего это стоит, я бы никогда этого не делал. int main()
для win & hellip;)
Ответы
Ответ 1
Чтение проекта С++ 17 §3.6.1/2:
... и он должен иметь объявленный тип возвращаемого типа int
,...
Итак, да, я бы сказал, что запрещено использовать вычет.
Почти такая же формулировка в последнем проекте С++ 14 (тот же раздел, что и проект С++ 17):
Он должен иметь объявленный тип возвращаемого типа int
,...
Просто личное размышление о возможных рассуждениях за этим, прочитав комментарии и другие ответы. Недопустимый вывод метода return-type (я думаю), потому что тогда тип возврата не известен компилятору, пока не увидит оператор return
. Также не редкость, что могут быть возвращены другие типы (которые неявно конвертируются в int
), что сделало бы неверный тип. Объявление типа возврата вверх-вниз (либо обычным старомодным способом, либо путем использования возвращаемого типа возврата) будет устанавливать тип при объявлении функции и может быть проверено компилятором тогда и там, чтобы быть правильным.
Что касается допустимых типов-псевдонимов, то это просто псевдонимы типа. Таким образом, например,
typedef int my_type;
my_type main() { ... }
действительно ничем не отличается от
int main() { ... }
Ответ 2
От 3.6.1/2 (внимание мое):
[...] он должен иметь объявленный тип возврата типа int
, но в противном случае его тип определяется реализацией.
Если auto
используется без возвращаемого возвращаемого типа, объявленный тип возвращаемого значения остается auto
, хотя тип возвращаемого возврата может быть чем-то другим. Разница между объявленными и выведенными явно не указана в стандарте, но 7.1.6.4/7 может пролить некоторый свет:
Когда оператор [...] a return
встречается в функции, объявленной с типом возвращаемого значения, который содержит тип заполнителя, выводимый тип возвращаемого значения [...] определяется из типа его инициализатора. В случае return
без операнда или с операндом типа void
объявленный тип возврата должен быть auto
, а выводимый тип возврата - void
.
Я понимаю, что с этим:
auto main(){ return 0; }
объявленный тип возвращаемого значения будет auto
, хотя выводимый тип возвращаемого значения будет int
. Согласно вышеизложенному 3.6.1/2, объявленный тип возврата main
должен быть int
. Поэтому это плохо сформировано.
Однако возвращаемый тип возврата считается объявленным типом возврата. Из раздела 7.1.6.4/2:
Если декларатор функции включает в себя тип возвращаемого типа (8.3.5), то trailing-return-type указывает объявленный тип возвращаемого значения функции.
$ cat a.cpp
auto main() -> int {}
$ g++ -Wall -std=c++14 a.cpp
$
Все кавычки идентичны как в С++ 14, так и в С++ 17.
Ответ 3
От 3.6.1 [basic.start.main]
1 Программа должна содержать глобальную функцию main, которая является назначенный старт программы....
2 Реализация не должна предопределить основную функцию. Эта функция не должна быть перегружена. Это должен иметь объявленный тип возврата типа int, но в противном случае его тип определяется реализацией...
Если бы стандарт ограничивал вычет, тогда я думаю, что словосочетание "объявленный тип возврата int" будет таким.
Ответ 4
Многие ответы хорошо упоминают цитаты из стандарта. Но есть еще одна тонкая проблема с auto
как возвращаемым типом.
В соответствии со стандартом С++ (где-то) оператор return
не является обязательным внутри main()
. Это прямо упоминается в Bjarne Stroustrup веб-сайт:
В С++ main()
не обязательно должен содержать явный оператор return
. В этом случае возвращаемое значение 0
означает успешное выполнение.
Это означает, что инструкция ниже действительна:
auto main () {}
Можно принять неявный оператор return 0;
непосредственно перед }
. Поэтому в таком случае auto
интерпретируется как int
. Тем не менее, из техничности С++ 14, auto
должен быть выведен на void
из-за отсутствия оператора возврата! Итак, "int
vs void
", что рассмотреть?
IMO - это предостережение, которое также предотвращает auto
как возвращаемый тип в логическом смысле.
Ответ 5
Как обсуждалось в разных комментариях, я действительно отсутствовал в стандарте, потому что то, что я считал копией С++ 14 FDIS, на самом деле не было такой (но, вместо этого, более старой версией), и слово "объявлено" было прокручено в соответствующий отрывок после CWG 1669.