簡體   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