Требуется ли мой тип возврата?

Форвардная декларация позволяет отложить определение фактического типа до файла реализации. Это разрешено в заголовке для указателей или ссылок на объявленный вперед тип.

Мне сказали, что:

Возврат по значению не требует определения типа. Достаточное объявление достаточно

Может ли кто-нибудь подтвердить или опровергнуть это с помощью фактической цитаты из стандарта? У меня сложилось впечатление, что это не является законным.

Ответы

Ответ 1

Возврат по значению не требует определения типа. Достаточное объявление достаточно

Объявление функции, возвращающей значение, не требует определения типа. Хорошо сформированная демо:

struct S;
S foo();
struct S {};
int main() {
    foo();
}
S foo() {}

Определение или вызов функции, которая возвращает значение, требует определения типа. Стандартный черновик [basic.def.odr]:

5 Точно одно определение класса требуется в блоке трансляции, если класс используется таким образом, чтобы тип класса был полным. [Пример:... [snip]... [Примечание. Правила деклараций и выражений описывают, в каких контекстах требуются полные типы классов. Тип класса T должен быть полным, если:

  • [надрез]
  • 5.9 определена функция с типом возвращаемого типа или типа аргумента типа T ([basic.def]) или вызвана ([expr.call]) или
  • [надрез]

Объявление функции с неполным возвращаемым типом неявно разрешено в силу запрета любым из правил в списке.

Правило переформулируется позже в стандарте, и оно смягчается исключением [dcl.fct] (благодаря @cpplearner для указания этого правила):

11 Типы не должны определяться в обратном порядке или типах параметров. Тип параметра или тип возвращаемого значения для определения функции не должен быть неполным (возможно, cv-квалифицированным) типом класса в контексте определения функции, если функция не удалена ([dcl.fct.def.delete]).


Неплохое демо:

struct S;
S foo(){} // oops
struct S {};

Другая неудачная демонстрация:

struct S;
S foo();
int main() {
    foo(); // oops
}
struct S {};
S foo() {}