在评估friend
和std::is_constructible
时,Clang和GCC似乎不尊重std::is_destructible
声明。
关于`is_constructible,cppreference.com says:
从与T无关的上下文和Args中的任何类型执行访问检查。仅考虑变量定义的直接上下文的有效性。
(该网站没有解释is_destructible
如何处理访问检查,但访问修饰符确实会影响is_destructible
的行为,因此我希望它的工作方式与is_constructible
相同。)
因此,在我看来,这段代码不应该编译,因为在检查的直接上下文中,构造函数和析构函数是可用的,如局部变量实例化所证明的那样:
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;
}
};
...但是Coliru compiles it without error(使用GCC或Clang)。
这是两个编译器中的错误(或至少是不合格),还是cppreference.com歪曲了标准,还是我误解了cppreference.com的声明?
这正是如此
从与
T
无关的上下文和Args
中的任何类型执行访问检查。
说。根据定义,“T
的朋友”并非“与T
无关”。
"immediate context"是一个艺术术语,但无论如何,句子是在谈论假设变量定义的直接背景,而不是使用is_constructible
。
让is_constructible
检查依赖于上下文是疯狂的;这意味着同一类型is_constructible<T, Args...>
在不同的上下文中具有不同的基类。