我對 C 20 概念相當陌生,我正在嘗試創建一個Foo具有基于非型別(列舉器)模板引數的完全專用實作的模板類。我已經使用下面的代碼測驗了我的想法:
// Foo.h
#include <concepts>
#include <iostream>
#include <type_traits>
enum class Type { A, B, C };
template<std::is_enum T1, std::is_enum T2>
constexpr bool isEnumSame() { return T1 == T2; }
template<Type T> concept isTypeA = isEnumSame<T, Type::A>;
template<Type T> concept isTypeB = isEnumSame<T, Type::B>;
template<Type T>
struct Foo
{
Foo() { std::cout << "Generic Foo\n"; }
};
template<Type T>
requires isTypeA<T>
struct Foo<T>
{
Foo() { std::cout << "Type A Foo\n"; }
};
template<Type T>
requires isTypeB<T>
struct Foo<T>
{
Foo() { std::cout << "Type B Foo\n"; }
};
// Foo.cpp
#include "Foo.h"
int main(void)
{
Foo<Type::C> testC;
Foo<Type::A> testA;
Foo<Type::B> testB;
return 0;
}
但是,我得到如下編譯器錯誤(我使用的是 g 11 和 gcc11):
error: insufficient contextual information to determine type
27 | Foo<Type::C> testC;
同樣對于Foo<Type::A> testA和Foo<Type::B> testB。有人可以告訴我我在這里可能做錯了什么嗎?此外,理想情況下,我希望定義類似于以下內容的完整專業:
template<isTypeA T>
struct Foo<T>
{
Foo() { Print("Type A Foo"); }
};
但上面會產生編譯器錯誤error: ‘isTypeA’ does not constrain a type。任何幫助將非常感激!
uj5u.com熱心網友回復:
std::is_enum不是一個概念,所以這個謂詞不會像我假設的那樣做:
template<std::is_enum T1, std::is_enum T2>
constexpr bool isEnumSame() { return T1 == T2; }
您可以Type直接取值。此外,您的概念行需要像這樣呼叫函式:
template<Type T1, Type T2>
constexpr bool isEnumSame() { return T1 == T2; }
template<Type T> concept isTypeA = isEnumSame<T, Type::A>();
template<Type T> concept isTypeB = isEnumSame<T, Type::B>();
如果您希望您isEnumSame對任何列舉都通用:
template <class T>
concept Enumeration = std::is_enum_v<T>;
template<Enumeration auto T1, Enumeration auto T2>
constexpr bool isEnumSame() { return T1 == T2; }
uj5u.com熱心網友回復:
有幾個問題:
-
template<std::is_enum T1, std::is_enum T2>is_enum是特征,不是概念。你可以使用類似的東西auto T1,然后requires std::is_enum_v<decltype(T1)>。 -
template<Type T> concept isTypeA = isEnumSame<T, Type::A>;`您忘記呼叫該函式,添加
().
但你實際上并不需要任何這種概念魔法。您可以完全專注Foo于列舉值:
template <>
struct Foo<Type::A> {...};
如果您出于某種原因不想獲得完整的專業化,您可以這樣做:
template <Type T>
requires (T == Type::A)
struct Foo<T> {...};
uj5u.com熱心網友回復:
首先,std::is_enum它不是一個概念,它只是一個普通的類,所以像這樣的語法template<std::is_enum T1, std::is_enum T2>只是定義了一個模板函式,它接受一個非型別的模板引數 type std::is_enum,這不是你所期望的,也沒有任何約束。
其次,模板引數的bool isEnumSame()不是型別而是列舉值,所以應該定義為template<auto T1, auto T2>.
如果需要對非型別模板引數的型別進行約束,可以直接使用decltype獲取其型別并使用requires -expression 進行約束,如下所示:
enum class Type { A, B, C };
template<auto T1, auto T2>
requires std::is_enum_v<decltype(T1)> && std::is_enum_v<decltype(T2)>
constexpr bool isEnumSame() { return T1 == T2; }
template<Type T> concept isTypeA = isEnumSame<T, Type::A>();
template<Type T> concept isTypeB = isEnumSame<T, Type::B>();
演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/438909.html
