我的std::is_constructible<void()>::value
结果不一致。我对标准的解释是它应该是假的。但是,使用libc ++和libstdc ++ *的Clang都是真的。 GCC和MSVC都给出了错误。哪个结果是正确的?
这是标准,N4527 [meta.unary.prop] / 7:
给出以下函数声明:
template <class T> add_rvalue_reference_t<T> create() noexcept;
模板特化的谓词条件 当且仅当,
is_constructible<T, Args...>
才会得到满足 对于一些发明的人来说,下面的变量定义会很好 变量t
:T t(create<Args>()...);
注意:此文本与C ++ 11(N3485)略有不同,其中create
未标记为noexcept
。但是,考虑到这一点,我的测试结果没有改变。
这是我对类型特征和标准定义的最小测试用例:
#include <type_traits>
static_assert(std::is_constructible<void()>::value, "assertion fired");
template<typename T>
std::add_rvalue_reference_t<T> create() noexcept;
template<typename T, typename... Args>
void foo() {
T t(create<Args>()...);
}
int main() {
foo<void()>();
}
foo<void()>
没有编译foo<void()>
没有编译foo<void()>
没有编译MSVC(版本19通过http://webcompiler.cloudapp.net/):
foo<void()>
没有编译(需要注释掉静态断言)__GLIBCXX__
选项和-stdlib
使用Clang时,未定义 * -stdlib=libstdc++
。我不确定libstdc ++是否实际正在使用。如果我对标准的解释是正确的,那么我不确定它是否是Clang或libc ++的错误。
答案 0 :(得分:7)
继续阅读。来自同一段:
执行访问检查,就好像在与
T
和。无关的上下文中一样 任何Args
。 只有当前上下文的有效性 考虑变量初始化。 [注意:评估 初始化可能导致副作用,例如实例化 类模板特化和函数模板特化, 生成隐式定义的函数,等等。这样的一面 效果不在“直接上下文”中,并且可能导致 程序不正确。 -end note ]
断言仅在实例化模板构造函数时失败。但是,正如在注释中清除的那样,该断言不在所考虑的变量定义的直接上下文中,因此不会影响其有效性&#34;。因此编译器可以将该定义计为有效,即使实际尝试构造void()
会导致格式错误的程序。
请注意,也允许编译器,而不是让is_constructible产生false,只是根据断言拒绝原始程序。