Подтвердить что ты не робот

Почему нельзя возвращать тип возврата?

Как и ожидалось, в С++ 11 происходит сбой: поскольку этот язык не имеет вывода типа возврата для стандартных функций болота:

auto main()
{
   return 0;
}

Однако С++ 14, поэтому я не могу объяснить следующую ошибку (с эквивалентными результатами в соединительной линии GCC, clang 3.8 и Visual Studio 2015):

error: 'main' must return 'int'

Есть ли проход в стандарте, который я не вижу, запрещающий вывод типа возврата для main? Или оба компилятора несовместимы?

(Для чего это стоит, я бы никогда этого не делал. int main() для win & hellip;)

4b9b3361

Ответ 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.