Files
cppdraft_translate/cppdraft/dcl/contract/func.md
2025-10-25 03:02:53 +03:00

12 KiB

[dcl.contract.func]

9 Declarations [dcl]

9.4 Function contract specifiers [dcl.contract]

9.4.1 General [dcl.contract.func]

function-contract-specifier-seq:
function-contract-specifier function-contract-specifier-seqopt

function-contract-specifier:
precondition-specifier
postcondition-specifier

precondition-specifier:
pre attribute-specifier-seqopt ( conditional-expression )

postcondition-specifier:
post attribute-specifier-seqopt ( result-name-introduceropt conditional-expression )

1

#

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]

2

#

The predicate ([basic.contract.general]) of a function contract assertion is its conditional-expression contextually converted to bool.

3

#

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]

4

#

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 F1 is a first declaration of f in one translation unit and a declaration F2 is a first declaration of f in another translation unit,F1 and F2 shall specify the samefunction-contract-specifier-seq, no diagnostic required.

5

#

A function-contract-specifier-seq S1 is the same as a function-contract-specifier-seq S2 if S1 and S2 consist of the same function-contract-specifiers in the same order.

A function-contract-specifier C1 on a function declaration D1 is the same as a function-contract-specifier C2 on a function declaration D2 if

their predicates P1 and P2 would satisfy the one-definition rule ([basic.def.odr]) if placed in function definitions on the declarations D1 and D2, respectively, except for

renaming of the parameters of f,

renaming of template parameters of a template enclosing , and

renaming of the result binding ([dcl.contract.res]), if any,

and, if D1 and D2 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 C1 and C2 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 P1 and P2, no diagnostic is required.

[Note 3:

Equivalentfunction-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 omittedvoid f() pre (b1) pre ([]{ return b2; }()); // error: closures have different types.void f() pre (b1); // error: function-contract-specifiers only partially repeatedint g() post(r : b1);int g() post(b1); // error: mismatched result-name-introducer presencenamespace 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]

6

#

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.

7

#

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]

8

#

[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]

9

#

The function contract assertions of a function are considered to be needed ([temp.inst]) when

the function is odr-used ([basic.def.odr]) or

the function is defined.

[Note 6:

Overload resolution does not considerfunction-contract-specifiers ([temp.deduct], [temp.inst]).

[Example 3: template void f(T t) pre( t == "" );template void f(T&& t);void g(){ f(5); // error: ambiguous} — end example]

— end note]