Reputation: 385385
I recently found out that the types of parameters in a non-defining function declaration may be of incomplete types. This is very exciting.
class A;
class B {
B(A a); // Legal! Wow!
};
The type is required to be complete only for the definition:
B::B(A a) {}; // error: ‘a’ has incomplete type
I've been trying to pin down the legalese for this, but my searches through C++11 for "[in]complete type" have yielded nothing of much interest, leading me to assume that these semantics are defined through an enigmatic maze of constructions.
Can you help me pin down the standard text that defines the above requirements for the types of function parameters being complete or otherwise, in function declarations vs definitions?
(9.2/10
and 9.4.2/2
give us the requirements for static
data member declarations and non-static
data member definitions in class definitions.)
Upvotes: 1
Views: 746
Reputation: 507373
See 8.3.5p9, which lays down the exact rules. For a = delete
definition, implementations are likely to accept incomplete parameter types too, retroactively (as was determined in a DR resolution by the C++ committee).
In particular, there is no action done on parameters or return values in a non-defining function declaration. Copying of arguments to parameters is done in the context of the caller. And destruction of parameters is done in the context of the callee, in the function definition. Destruction of the return value is done in the context of the caller in a function call except if the call is the topmost expression or right operand of a topmost comma operator in a decltype
. Then no destruction happens because no temporary is created as a special case (to help SFINAE libraries).
Upvotes: 5
Reputation: 385385
There doesn't appear to be anything directly addressing this. It may be that it's allowed because it is not disallowed.
7.1.1/9
tells us that it's ok for an extern
declaration (which is semantically similar to a member function declaration), and shows us non-normatively that types in such declarations may be incomplete:
[C++11: 7.1.1/9]:
The name of a declared but undefined class can be used in anextern
declaration. Such a declaration can only be used in ways that do not require a complete class type. [ Example:struct S; extern S a; extern S f(); extern void g(S); void h() { g(a); // error: S is incomplete f(); // error: S is incomplete }
—end example ]
[C++11: 8.3.5/9]:
Types shall not be defined in return or parameter types. The type of a parameter or the return type for a function definition shall not be an incomplete class type (possibly cv-qualified) unless the function definition is nested within the member-specification for that class (including definitions in nested classes defined within the class).
[C++11: 5.2.2/4]:
[..] When a function is called, the parameters that have object type shall have completely-defined object type. [ Note: this still allows a parameter to be a pointer or reference to an incomplete class type. However, it prevents a passed-by-value parameter to have an incomplete class type. —end note ] [..]
Upvotes: 0