14

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

I have been told что:

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

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

+8

Вы можете быть ясно, что вы думаете, это не законно, точно? Например, фактический образец кода, который вы считаете незаконным? – Yakk

+1

Это относится к объявлениям функций, а не к определениям. И нет, это не цитата из стандарта. – juanchopanza

+4

Возможно, я должен был сказать: «Возврат по значению не требует определения типа ** при объявлении функции **. Достаточное объявление достаточно». Вам нужно определение, когда вы определяете функцию и когда вы ее вызываете. –

ответ

25

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

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

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() {} 
+6

Упрощенный, потому что это похоже на подтверждение в стандарте, который ищет OP. –

+0

Справа. Если вы думаете об этом с точки зрения дизайна компилятора, это имеет смысл: тип должен быть полным, если компилятор должен знать его размер/выравнивание. Это важно для генерации кода для выражений, а также для настройки структуры возврата для функции. Но они, конечно, не имеют значения для прямого объявления, которое не появляется в сгенерированном коде и только обновляет внутренние структуры компилятора. – wchargin