![](/img/trans.png)
[英]Is passing of a function pointer through a class type in non-type template parameter allowed in C++20?
[英]Full specialisation of a class template using a C++20 concept of a non-type template parameter
我是 C++20 概念的新手,我正在嘗試創建一個模板 class 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
。 任何幫助將非常感激!
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; }
有幾個問題:
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>;`
您忘記撥打 function,添加()
。
但你實際上並不需要任何這種概念魔法。 您可以將Foo
完全專門化為枚舉值:
template <>
struct Foo<Type::A> {...};
如果您出於某種原因不想完全專業化,您可以這樣做:
template <Type T>
requires (T == Type::A)
struct Foo<T> {...};
首先, std::is_enum
不是一個概念,它只是一個普通的 class,所以像template<std::is_enum T1, std::is_enum T2>
這樣的語法只是定義了一個模板 function,它接受一個非類型模板參數鍵入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>();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.