Возврат по значению не требует определения типа. Достаточная декларация достаточна
Объявление функции, возвращающей значение, не требует определения типа. Хорошо сформированная демо-версия:
struct S;
S foo();
struct S {};
int main() {
foo();
}
S foo() {}
Определение или вызов функции, возвращающей значение, требует определения типа. Стандартный проект [basic.def.odr]:
5 Точно одно определение класса требуется в единице трансляции, если класс используется таким образом, что требует тип класса, чтобы быть полным. [Пример: ... [snip] ... [Примечание. Правила деклараций и выражений описывают, в каких контекстах требуются полные типы классов. тип класса Т должен быть полным, если:
- [надрез]
- 5.9 функция с типом возвращаемого типа аргумента или типа Т определяется ([basic.def]) или называется ([выражение .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() {}
Вы можете быть ясно, что вы думаете, это не законно, точно? Например, фактический образец кода, который вы считаете незаконным? – Yakk
Это относится к объявлениям функций, а не к определениям. И нет, это не цитата из стандарта. – juanchopanza
Возможно, я должен был сказать: «Возврат по значению не требует определения типа ** при объявлении функции **. Достаточное объявление достаточно». Вам нужно определение, когда вы определяете функцию и когда вы ее вызываете. –