Clang and GCC appear not to honor friend
declarations when evaluating std::is_constructible
and std::is_destructible
.
Regarding `is_constructible, cppreference.com says:
Access checks are performed as if from a context unrelated to T and any of the types in Args. Only the validity of the immediate context of the variable definition is considered.
(The site doesn't explain how is_destructible
deals with access checks, but access modifiers do affect the behavior of is_destructible
in general, so I'd expect it to work the same way as is_constructible
.)
Therefore, it seems to me that this code should not compile, since in the immediate context of the check the constructor and destructor are available, as evidenced by the local variable instantiation:
class Private
{
Private() {}
~Private() {}
friend class Friend;
};
class Friend
{
public:
Friend()
{
// Both of these should fire, but they do not.
static_assert(
!std::is_constructible<Private>::value,
"the constructor is public");
static_assert(
!std::is_destructible<Private>::value,
"the destructor is public");
// There is no error here.
Private p;
}
};
...but Coliru compiles it without error (using either GCC or Clang).
Is this a bug (or at least a nonconformity) in both compilers, or is cppreference.com misrepresenting the standard, or am I misunderstanding cppreference.com's statement?
This is exactly what
Access checks are performed as if from a context unrelated to
T
and any of the types inArgs
.
says. "A friend of T
" is by definition not "unrelated to T
".
"immediate context" is a term of art, but in any event the sentence is talking about the immediate context of the hypothetical variable definition, not the use of is_constructible
.
It would be madness to make the is_constructible
check context-dependent; that would mean that the same type, is_constructible<T, Args...>
, has different base classes in different contexts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With