【发布时间】:2017-01-19 12:01:43
【问题描述】:
在评估 std::is_constructible 和 std::is_destructible 时,Clang 和 GCC 似乎不遵守 friend 声明。
关于`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.C.我不知道标准语言中的“即时上下文”是什么意思,但令我非常惊讶的是
is_constructible的结果并没有告诉你对象是否可以在非常下一行代码中构造 i>. -
另一种选择是同一类型 (
is_constructible<T, Args..>)具有不同的基类,具体取决于使用的位置。 -
@T.C.好的,我明白了我想象的版本是如何无法实现的,而且在类型系统方面也有些荒谬。我想在阅读this 之后我对“直接上下文”的理解更好一些,但我当然不觉得这是一个直观易懂的短语。
标签: c++ c++11 gcc clang access-modifiers