繁体   English   中英

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

[英]Checking for a default Constructor using class templates with std::void_t

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

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 [提取,强调我的]:

[...] 一个函数是用户提供的,如果它是用户声明的,并且在第一次声明时没有明确默认或删除。

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

C++20 中的聚合

从 C++20 开始,特别是由于P1008R1禁止使用用户声明的构造函数的聚合)的实现,上面涵盖的大多数经常令人惊讶的聚合行为都已得到解决,特别是不再允许聚合具有用户声明的构造函数,对类作为聚合的要求比仅仅禁止用户提供的构造函数更严格。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM