11 Declarators [dcl.decl]

11.4 Function definitions [dcl.fct.def]

11.4.1 In general [dcl.fct.def.general]

Определения функций имеют вид

function-definition:
	attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body
function-body:
	ctor-initializeropt compound-statement
	function-try-block
	= default ;
	= delete ;

Любую неформальную ссылку на тело функции следует интерпретировать как ссылку на нетерминал function-body. Необязательный параметр attribute-specifier-seqв a function-definition относится к функции. А virt-specifier-seqможет быть частью, function-definition только если это member-declaration.

В a function-definition, либо, либо должно быть правильно сформированным объявлением функции, как описано в . Функция должна быть определена только в пространстве имен или в области класса.void declarator;declarator;[dcl.fct]

[ Example: Простой пример полного определения функции:

int max(int a, int b, int c) {
  int m = (a > b) ? a : b;
  return (m > c) ? m : c;
}

Вот int это decl-specifier-seq; max(int a, int b, int c) это declarator; { /* ... */ } это function-body. ]end example

A ctor-initializer используется только в конструкторе; видеть[class.ctor] и[class.init].

[ Note: A cv-qualifier-seqвлияет на типthis в теле функции-члена; см[dcl.ref]. ]end note

[ Note: Неиспользуемые параметры называть не нужно. Например,

void print(int a, int) {
  std::printf("a = %d\n",a);
}

end note]

В function-body, a function-local predefined variable обозначает объект блочной области со статической продолжительностью хранения, которая неявно определена (см[basic.scope.block]. Раздел "Ресурсы" ).

Локальная для функции предопределенная переменная _­_­func_­_­определяется так, как если бы определение формы

static const char __func__[] = "function-name";

был предоставлен, гдеfunction-name - строка, определяемая реализацией. Не указано, имеет ли такая переменная адрес, отличный от адреса любого другого объекта в программе.103 [Example:

struct S {
  S() : s(__func__) { }             // OK
  const char* s;
};
void f(const char* s = __func__);   // error: _­_­func_­_­ is undeclared

end example]

Реализациям разрешено предоставлять дополнительные предопределенные переменные с соответствующими именами reserved to the implementation. Если предопределенной переменной нет odr-used, ее строковое значение не обязательно должно присутствовать в образе программы.

11.4.2 Explicitly-defaulted functions [dcl.fct.def.default]

Определение функции в форме:

attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt  = default ;

называетсяexplicitly-defaulted определением. Функция, которая явно задана по умолчанию, должна

  • быть специальной функцией-членом,

  • иметь один и тот же объявленный тип функции (за исключением возможных различий ref-qualifiers и за исключением того, что в случае конструктора копирования или оператора присваивания копии тип параметра может быть «ссылкой на неконстантныйT», гдеT является именем класса функции-члена) как если это было неявно объявлено, и

  • не иметь аргументов по умолчанию.

Явно заданная по умолчанию функция, которая не определена как удаленная, может быть объявлена constexpr только в том случае, если она была неявно объявлена ​​как constexpr. Если функция явно задана по умолчанию при ее первом объявлении, она неявно считаетсяconstexpr таковой, если неявное объявление будет.

Если функция, для которой явно задано значение по умолчанию, объявляется с помощью noexcept-specifier, который не создает такую ​​же спецификацию исключения, как неявное объявление ([except.spec]), тогда

  • если функция явно задана по умолчанию при ее первом объявлении, она определяется как удаленная;

  • в противном случае программа имеет неправильный формат.

[Example:

struct S {
  constexpr S() = default;              // ill-formed: implicit S() is not constexpr
  S(int a = 0) = default;               // ill-formed: default argument
  void operator=(const S&) = default;   // ill-formed: non-matching return type
  ~S() noexcept(false) = default;       // deleted: exception specification does not match
private:
  int i;
  S(S&);                                // OK: private copy constructor
};
S::S(S&) = default;                     // OK: defines copy constructor

end example]

Явно заданные по умолчанию функции и неявно объявленные функции совместно называютсяdefaulted функциями, и реализация должна предоставлять для них неявные определения ([class.ctor] [class.dtor],[class.copy]), что может означать определение их как удаленных. Функция - user-provided это если она объявлена ​​пользователем и не была явно задана по умолчанию или удалена при ее первом объявлении. Предоставляемая пользователем функция с явно заданным по умолчанию значением (т. Е. Явно заданная по умолчанию после ее первого объявления) определяется в точке, где она явно задана по умолчанию; если такая функция неявно определена как удаленная, программа имеет неправильный формат. [ Note: Объявление функции по умолчанию после ее первого объявления может обеспечить эффективное выполнение и краткое определение, в то же время обеспечивая стабильный двоичный интерфейс для развивающейся базы кода. ]end note

[Example:

struct trivial {
  trivial() = default;
  trivial(const trivial&) = default;
  trivial(trivial&&) = default;
  trivial& operator=(const trivial&) = default;
  trivial& operator=(trivial&&) = default;
  ~trivial() = default;
};

struct nontrivial1 {
  nontrivial1();
};
nontrivial1::nontrivial1() = default;   // not first declaration

end example]

11.4.3 Deleted definitions [dcl.fct.def.delete]

Определение функции в форме:

attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt  = delete ;

называется аdeleted definition. Функция с удаленным определением также называется функциейdeleted function.

Программа, которая неявно или явно ссылается на удаленную функцию, за исключением ее объявления, плохо сформирована. [ Note: Это включает неявный или явный вызов функции и формирование указателя или указателя на член функции. Это применимо даже к ссылкам в выражениях, которые потенциально не оцениваются. Если функция перегружена, на нее ссылаются только в том случае, если функция выбрана разрешением перегрузки. Неявное odr-use выражение виртуальной функции само по себе не является ссылкой. ]end note

[ Example: Можно принудительно применить инициализацию не по умолчанию и нецелую инициализацию с помощью

struct onlydouble {
  onlydouble() = delete;                // OK, but redundant
  onlydouble(std::intmax_t) = delete;
  onlydouble(double);
};

end example]

[ Example: Можно предотвратить использование класса в определенных случаях new-expressions , используя удаленные определения пользователя, объявленногоoperator new для этого класса.

struct sometype {
  void* operator new(std::size_t) = delete;
  void* operator new[](std::size_t) = delete;
};
sometype* p = new sometype;     // error, deleted class operator new
sometype* q = new sometype[3];  // error, deleted class operator new[]

end example]

[ Example: Можно сделать класс не копируемым, то есть доступным только для перемещения, используя удаленные определения конструктора копирования и оператора присваивания копии, а затем предоставив определения по умолчанию для конструктора перемещения и оператора присваивания перемещения.

struct moveonly {
  moveonly() = default;
  moveonly(const moveonly&) = delete;
  moveonly(moveonly&&) = default;
  moveonly& operator=(const moveonly&) = delete;
  moveonly& operator=(moveonly&&) = default;
  ~moveonly() = default;
};
moveonly* p;
moveonly q(*p);                 // error, deleted copy constructor

end example]

Удаленная функция неявно является файломinline function. [ Применяется к удаленным определениям. ] Удаленное определение функции должно быть первым объявлением функции или, для явной специализации шаблона функции, первым объявлением этой специализации. Неявно объявленная функция выделения или освобождения ( ) не должна определяться как удаленная. [Note: one-definition rule end note[basic.stc.dynamic]Example:

struct sometype {
  sometype();
};
sometype::sometype() = delete;  // ill-formed; not first declaration

end example]