9 Declarations [dcl]

9.4 Function contract specifiers [dcl.contract]

9.4.1 General [dcl.contract.func]

A function contract assertion is a contract assertion ([basic.contract.general]) associated with a function.
A precondition-specifier introduces a precondition assertion, which is a function contract assertion associated with entering a function.
A postcondition-specifier introduces a postcondition assertion, which is a function contract assertion associated with exiting a function normally.
[Note 1: 
A postcondition assertion is not associated with exiting a function in any other fashion, such as via an exception ([expr.throw]) or via a call to longjmp ([csetjmp.syn]).
— end note]
The predicate ([basic.contract.general]) of a function contract assertion is its conditional-expression contextually converted to bool.
Each function-contract-specifier of a function-contract-specifier-seq (if any) of an unspecified first declaration ([basic.def]) of a function introduces a corresponding function contract assertion for that function.
The optional attribute-specifier-seq following pre or post appertains to the introduced contract assertion.
[Note 2: 
The function-contract-specifier-seq of a lambda-declarator applies to the function call operator or operator template of the corresponding closure type ([expr.prim.lambda.closure]).
— end note]
A declaration D of a function or function template f that is not a first declaration shall have either no function-contract-specifier-seq or the same function-contract-specifier-seq (see below) as any first declaration F reachable from D.
If D and F are in different translation units, a diagnostic is required only if D is attached to a named module.
If a declaration is a first declaration of f in one translation unit and a declaration is a first declaration of f in another translation unit, and shall specify the same function-contract-specifier-seq, no diagnostic required.
A function-contract-specifier-seq is the same as a function-contract-specifier-seq if and consist of the same function-contract-specifiers in the same order.
A function-contract-specifier on a function declaration is the same as a function-contract-specifier on a function declaration if
  • their predicates and would satisfy the one-definition rule ([basic.def.odr]) if placed in function definitions on the declarations and , respectively, except for and, if and are in different translation units, corresponding entities defined within each predicate behave as if there is a single entity with a single definition, and
  • both and specify a result-name-introducer or neither do.
If this condition is not met solely due to the comparison of two lambda-expressions that are contained within and , no diagnostic is required.
[Note 3: 
Equivalent function-contract-specifier-seqs apply to all uses and definitions of a function across all translation units.
— end note]
[Example 1:  bool b1, b2; void f() pre (b1) pre ([]{ return b2; }()); void f(); // OK, function-contract-specifiers omitted void f() pre (b1) pre ([]{ return b2; }()); // error: closures have different types. void f() pre (b1); // error: function-contract-specifiers only partially repeated int g() post(r : b1); int g() post(b1); // error: mismatched result-name-introducer presence namespace N { void h() pre (b1); bool b1; void h() pre (b1); // error: function-contract-specifiers differ according to // the one-definition rule ([basic.def.odr]). } — end example]
A virtual function ([class.virtual]), a deleted function ([dcl.fct.def.delete]), or a function defaulted on its first declaration ([dcl.fct.def.default]) shall not have a function-contract-specifier-seq.
If the predicate of a postcondition assertion of a function f odr-uses ([basic.def.odr]) a non-reference parameter of f, that parameter and the corresponding parameter on all declarations of f shall have const type.
[Note 4: 
This requirement applies even to declarations that do not specify the postcondition-specifier.
Parameters with array or function type will decay to non-const types even if a const qualifier is present.
[Example 2: int f(const int i[10]) post(r : r == i[0]); // error: i has type const int * (not int* const). — end example]
— end note]
[Note 5: 
The function contract assertions of a function are evaluated even when invoked indirectly, such as through a pointer to function or a pointer to member function.
A pointer to function, pointer to member function, or function type alias cannot have a function-contract-specifier-seq associated directly with it.
— end note]
The function contract assertions of a function are considered to be needed ([temp.inst]) when
[Note 6: 
Overload resolution does not consider function-contract-specifiers ([temp.deduct], [temp.inst]).
[Example 3: template <typename T> void f(T t) pre( t == "" ); template <typename T> void f(T&& t); void g() { f(5); // error: ambiguous } — end example]
— end note]