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
[ 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, ее строковое значение не обязательно должно присутствовать в образе программы.
Определение функции в форме:
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 ]
Определение функции в форме:
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 ]