c++ - 使用带有 std::void_t 的类模板检查默认构造函数

标签 c++ c++11 c++17 template-meta-programming

下面是试图在编译时检查默认构造函数是否存在的代码段。编译这个

clang version 11.0.0
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin
使用选项 clang++ --std=c++17 -o test_default_ctor test_default_ctor.cpp
#include <type_traits>

template<typename T, typename = void>
struct has_default_ctor_1 : std::false_type {}; 

template<typename T>
struct has_default_ctor_1<T, std::void_t<decltype(T())>> : std::true_type {}; 

template<typename T, typename = void>
struct has_default_ctor_2 : std::false_type {}; 

template<typename T>
struct has_default_ctor_2<T, std::void_t<decltype(T{})>> : std::true_type {}; 

struct Test1 {
    Test1() = default;
};

struct Test2 {
    Test2() {}
};

struct Test3 {
    Test3() = delete;
};

int main() {
    static_assert(has_default_ctor_1<Test1>::value, "Test has default ctor");
    static_assert(has_default_ctor_2<Test1>::value, "Test has default ctor");
    static_assert(has_default_ctor_1<Test2>::value, "Test has default ctor");
    static_assert(has_default_ctor_2<Test2>::value, "Test has default ctor");
    static_assert(not has_default_ctor_1<Test3>::value, "Test has default ctor");
    static_assert(not has_default_ctor_2<Test3>::value, "Test has default ctor");
}
编译的输出将是
test_default_ctor.cpp:33:5: error: static_assert failed due to requirement '!has_default_ctor_2<Test3, void>::value' "Test has default ctor"
    static_assert(not has_default_ctor_2<Test3>::value, "Test has default ctor");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
问题是为什么使用 ()对比 {}模板特化中的构造函数调用使它在一种情况下工作但在另一种情况下不起作用?

最佳答案

template<typename T>
struct has_default_ctor_2<T, std::void_t<decltype(T{})>> : std::true_type {}; 

当您检查是否T{}格式良好,您还允许可以通过聚合初始化来初始化的类型。 Test3是 C++20 之前的聚合类,因为它没有用户提供的构造函数。来自 [dcl.fct.def.default]/5 [提取,重点 矿]:

[...] A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.


有关不同标准版本上聚合的详细信息,请参见例如:
  • The fickle aggregate

  • Aggregates in C++20

    As of C++20, particularly due to the implementation of P1008R1 (Prohibit aggregates with user-declared constructors) most of the frequently surprising aggregate behaviour covered above has been addressed, specifically by no longer allowing aggregates to have user-declared constructors, a stricter requirement for a class to be an aggregate than just prohibiting user-provided constructors.

    关于c++ - 使用带有 std::void_t 的类模板检查默认构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64959561/

    相关文章:

    c++ - 链接器想要我已经链接的库

    c++ - 不清楚的复制赋值运算符示例

    c++ - 了解 SFINAE 示例

    c++ - 为什么 std::filesystem::path::root_name() 返回空字符串?

    c++ - g++ 对 std::filesystem::last_write_time 的重大更改

    c++ - 如何获取采用可调用项来匹配类型的函数模板?

    c++ - 错误 : call of overloaded ‘max(int, int)’ is ambiguous

    C++ 'class' 类型重定义错误

    c++ - 0x00051526处未处理的异常读取位置0x00000004时访问冲突

    c++ - 如何配置 Eclipse 以使用特定的 MinGW 工具链