If a class has inaccessible (private) destructor, can it be passed by value to a function as in the following example?
class A {
~A() {}
};
// ok in GCC and Clang, error in MSVC
void f(A) {}
GCC and Clang both accept this program, while MSVC rejects it with the error:
<source>(6): error C2248: 'A::~A': cannot access private member declared in class 'A'
Online demo: https://gcc.godbolt.org/z/884176rWW
Which compiler is correct here, according to the standard, or is it not specified?
It is implementation-defined whether a parameter is destroyed when the function in which it is defined exits ([stmt.return], [except.ctor]) or at the end of the enclosing full-expression; parameters are always destroyed in the reverse order of their construction. The initialization and destruction of each parameter occurs within the context of the full-expression ([intro.execution]) where the function call appears.
[Example 2: The access ([class.access.general]) of the constructor, conversion functions, or destructor is checked at the point of call. [...] — end example]
Microsoft chooses to destroy arguments in the callee (i.e., the code for f
would include a call the the destructor of A
), but it erroneously also does the access check there.
Access checks should only be done in the callee. If you called the function somewhere the destructor was accessible:
class A {
~A() {}
friend int main();
};
void f(A) {}
int main() {
f(A{});
}
This should compile, even if the implementation actually destroys the parameter inside f
.