9

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?

Kyle Strand
  • 15,941
  • 8
  • 72
  • 167
  • This is basically a quote straight from the standard (with a couple words changed). Also, that's not what "immediate context" means. – T.C. Sep 12 '16 at 05:18
  • @T.C. I don't know what "immediate context" means in standardese, but it surprises me immensely that the result of `is_constructible` tells you nothing about whether or not the object can be constructed in the *very next line of code*. – Kyle Strand Sep 12 '16 at 05:20
  • 3
    The alternative is that the same type (`is_constructible`) *has different base classes* depending on where it is used. – T.C. Sep 12 '16 at 05:22
  • @T.C. Okay, I see how the version I was imagining would be impossible to implement and also somewhat nonsensical in terms of the type system. I think I understand "immediate context" a little better after reading [this](http://stackoverflow.com/q/15260685/1858225), but I certainly don't feel that it's an intuitively understandable phrase. – Kyle Strand Sep 12 '16 at 05:45

1 Answers1

7

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.

Community
  • 1
  • 1
T.C.
  • 133,968
  • 17
  • 288
  • 421