簡體   English   中英

使用非類型模板參數的 C++20 概念對 class 模板進行完全特化

[英]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> testAFoo<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; }

有幾個問題:

  1.  template<std::is_enum T1, std::is_enum T2>

    is_enum是一個特征,而不是一個概念。 您可以使用auto T1之類的東西,然后requires std::is_enum_v<decltype(T1)>

  2.  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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM