Нужно ли определять мой тип возврата?

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

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

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

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


person Jonathan Mee    schedule 31.01.2017    source источник
comment
Можете ли вы уточнить, что именно вы считаете незаконным? Например, фактический образец кода, который вы считаете незаконным?   -  person Yakk - Adam Nevraumont    schedule 31.01.2017
comment
Это относится к объявлениям функций, а не к определениям. И нет, это не цитата из стандарта.   -  person juanchopanza    schedule 31.01.2017
comment
Возможно, мне следовало сказать, что Возврат по значению не требует определения типа когда вы объявляете функцию. Достаточно предварительного объявления. Вам нужно определение, когда вы определяете функцию и когда вы ее вызываете.   -  person Christian Hackl    schedule 31.01.2017
comment
Кстати, это относится и к параметрам. Вы можете попробовать это в любом компиляторе. Я просто изо всех сил пытаюсь найти точное подтверждение в стандарте.   -  person Christian Hackl    schedule 31.01.2017
comment
Форвардное объявление позволяет нам отложить объявление фактического типа до файла реализации Нет, это не так. Подсказка в названии; вы объявляете свой тип прямо здесь.   -  person Lightness Races in Orbit    schedule 01.02.2017
comment
@LightnessRacesinOrbit Спасибо, я исправил это на: определение   -  person Jonathan Mee    schedule 01.02.2017


Ответы (1)


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

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

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

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

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

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

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

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

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


Плохо сформированная демонстрация:

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

Еще одна плохо сформированная демонстрация:

struct S;
S foo();
int main() {
    foo(); // oops
}
struct S {};
S foo() {
    return {};
}
person eerorika    schedule 31.01.2017
comment
Проголосовал, потому что это, кажется, именно то подтверждение в стандарте, которое искал ОП. - person Christian Hackl; 31.01.2017
comment
Верно. Если вы думаете об этом с точки зрения дизайна компилятора, это имеет смысл: тип должен быть полным, если компилятору нужно знать его размер/выравнивание. Они имеют значение при генерации кода для выражений, а также при настройке возвращаемой структуры для функции. Но они, конечно, не имеют значения для предварительного объявления, которое не появляется в сгенерированном коде и только обновляет внутренние структуры компилятора. - person wchargin; 01.02.2017