Files
2025-10-25 03:02:53 +03:00

216 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[dcl.contract.func]
# 9 Declarations [[dcl]](./#dcl)
## 9.4 Function contract specifiers [[dcl.contract]](dcl.contract#func)
### 9.4.1 General [dcl.contract.func]
[function-contract-specifier-seq:](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")
[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[function-contract-specifier:](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")
[*precondition-specifier*](#nt:precondition-specifier "9.4.1General[dcl.contract.func]")
[*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")
[precondition-specifier:](#nt:precondition-specifier "9.4.1General[dcl.contract.func]")
pre [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
[postcondition-specifier:](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")
post [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ( [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]")opt [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4613)
A [*function contract assertion*](#def:contract_assertion,function "9.4.1General[dcl.contract.func]") is a contract assertion ([[basic.contract.general]](basic.contract.general "6.11.1General"))
associated with a function[.](#1.sentence-1)
A [*precondition-specifier*](#nt:precondition-specifier "9.4.1General[dcl.contract.func]") introduces a [*precondition assertion*](#def:assertion,precondition "9.4.1General[dcl.contract.func]"),
which is a function contract assertion
associated with entering a function[.](#1.sentence-2)
A [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]") introduces a [*postcondition assertion*](#def:assertion,postcondition "9.4.1General[dcl.contract.func]"),
which is a function contract assertion
associated with exiting a function normally[.](#1.sentence-3)
[*Note [1](#note-1)*:
A postcondition assertion
is not associated with exiting a function
in any other fashion,
such as via an exception ([[expr.throw]](expr.throw "7.6.18Throwing an exception"))
or via a call to longjmp ([[csetjmp.syn]](csetjmp.syn "17.14.3Header <csetjmp> synopsis"))[.](#1.sentence-4)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4635)
The predicate ([[basic.contract.general]](basic.contract.general "6.11.1General"))
of a function contract assertion
is its [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") contextually converted to bool[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4641)
Each [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") of a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") (if any)
of an unspecified first declaration ([[basic.def]](basic.def "6.2Declarations and definitions"))
of a function
introduces a corresponding function contract assertion for that function[.](#3.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") following pre or post appertains to the introduced contract assertion[.](#3.sentence-2)
[*Note [2](#note-2)*:
The [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") of a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") applies to the function call operator or operator template
of the corresponding closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2Closure types"))[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4657)
A declaration D of a function or function template *f* that is not a first declaration shall have either
no [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") or the same [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") (see below)
as any first declaration F reachable from D[.](#4.sentence-1)
If D and F are
in different translation units,
a diagnostic is required only if D is attached to a named module[.](#4.sentence-2)
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 same[*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]"), no diagnostic required[.](#4.sentence-3)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4675)
A [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") S1 is the same as
a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") S2 if S1 and S2 consist of
the same [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* in the same order[.](#5.sentence-1)
A [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") C1 on a function declaration D1 is
the same as
a [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") C2 on a function declaration D2 if
- [(5.1)](#5.1)
their predicates P1 and P2 would
satisfy the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
if placed in function definitions on
the declarations D1 and D2, respectively, except for
* [(5.1.1)](#5.1.1)
renaming of the parameters of *f*,
* [(5.1.2)](#5.1.2)
renaming of template parameters of
a template enclosing , and
* [(5.1.3)](#5.1.3)
renaming of the result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object")), 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
- [(5.2)](#5.2)
both C1 and C2 specify a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") or neither do[.](#5.sentence-2)
If this condition is not met
solely due to the comparison of two [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* that are contained within P1 and P2,
no diagnostic is required[.](#5.sentence-3)
[*Note [3](#note-3)*:
Equivalent[*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")*s* apply to all uses and definitions
of a function across all translation units[.](#5.sentence-4)
— *end note*]
[*Example [1](#example-1)*: bool b1, b2;
void f() pre (b1) pre ([]{ return b2; }());void f(); // OK, [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* omittedvoid f() pre (b1) pre ([]{ return b2; }()); // error: closures have different types.void f() pre (b1); // error: [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* only partially repeatedint g() post(r : b1);int g() post(b1); // error: mismatched [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") presencenamespace N {void h() pre (b1); bool b1; void h() pre (b1); // error: [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* differ according to// the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")).} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4745)
A virtual function ([[class.virtual]](class.virtual "11.7.3Virtual functions")),
a deleted function ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions")),
or a function defaulted on its first declaration ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions"))
shall not have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4751)
If the predicate of a postcondition assertion
of a function *f* odr-uses ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
a non-reference parameter of *f*,
that parameter
and the corresponding parameter on all declarations of *f* shall have const type[.](#7.sentence-1)
[*Note [4](#note-4)*:
This requirement applies
even to declarations that do not specify the [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")[.](#7.sentence-2)
Parameters with array or function type
will decay to non-const types
even if a const qualifier is present[.](#7.sentence-3)
[*Example [2](#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](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4773)
[*Note [5](#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[.](#8.sentence-1)
A pointer to function,
pointer to member function,
or function type alias
cannot have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") associated directly with it[.](#8.sentence-2)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4785)
The function contract assertions of a function
are considered to be [*needed*](#def:needed,function_contract_assertion "9.4.1General[dcl.contract.func]") ([[temp.inst]](temp.inst "13.9.2Implicit instantiation")) when
- [(9.1)](#9.1)
the function is odr-used ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")) or
- [(9.2)](#9.2)
the function is defined[.](#9.sentence-1)
[*Note [6](#note-6)*:
Overload resolution does not consider[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"), [[temp.inst]](temp.inst "13.9.2Implicit instantiation"))[.](#9.sentence-2)
[*Example [3](#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*]