Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is_constructible and is_destructible unaffected by friend declarations

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?

like image 560
Kyle Strand Avatar asked Sep 12 '16 05:09

Kyle Strand


1 Answers

This is exactly what

Access checks are performed as if from a context unrelated to T and any of the types in Args.

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.

like image 159
T.C. Avatar answered Nov 15 '22 21:11

T.C.