std::is_constructible<void()>::value 的正确结果是什么?

What is the correct result of std::is_constructible<void()>::value?

本文关键字:结果 结果是 value 是什么 constructible is lt void std gt      更新时间:2023-10-16

我得到std::is_constructible<void()>::value不一致的结果。我对标准的解释是它应该是假的。然而,Clang在libc++和libstdc++*中都给出了true。GCC和MSVC都给出false。哪个结果是正确的?

<标题> Standardese h1> 是标准,N4527 [meta.一元。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()>();   
}
<标题>结果:

Clang (HEAD, libc++):

  • 静态断言已通过
  • foo<void()>未编译

Clang (HEAD, libstdc++)*:

  • 静态断言已通过
  • foo<void()>未编译

GCC (HEAD, libstdc++):

  • 静态断言失败
  • foo<void()>未编译

MSVC (version 19 via http://webcompiler.cloudapp.net/):

  • 静态断言失败
  • foo<void()>没有编译(需要注释掉静态断言)

* __GLIBCXX__在Clang没有-stdlib选项和-stdlib=libstdc++选项时没有定义。我不确定是否libstdc++是实际上正在使用。如果我对标准的解释是正确的,那么我不确定这是Clang还是libc++的bug。

继续阅读。来自同一段:

访问检查就像在与T和无关的上下文中执行一样Args中的任何一个。对象的当前上下文的有效性考虑变量初始化。 [备注:的实例化会导致副作用类模板特化和函数模板特化,隐式定义函数的生成等等。这样的方效果不在"直接上下文"中,并且可能导致程序格式错误。 -end note]

断言只有在模板构造函数实例化时才会失败。然而,正如在说明中澄清的那样,该断言并不在所考虑的变量定义的直接上下文中,因此不影响其"有效性"。因此,编译器可以认为该定义是有效的,即使实际上试图构造void()会导致错误格式的程序。

请注意,编译器也可以根据断言拒绝原始程序,而不是让is_constructible产生false。

相关文章: