首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用非类型模板参数的C++20概念对类模板进行完全专门化

使用非类型模板参数的C++20概念对类模板进行完全专门化
EN

Stack Overflow用户
提问于 2022-03-02 06:45:04
回答 3查看 157关注 0票数 0

我对C++20概念相当陌生,我正在尝试创建一个模板类Foo,该类具有基于非类型(枚举器)模板参数的完全专业化的实现。我使用以下代码测试了我的想法:

代码语言:javascript
复制
// 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"; }
};
代码语言:javascript
复制
// 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):

代码语言:javascript
复制
error: insufficient contextual information to determine type
   27 |       Foo<Type::C> testC;

Foo<Type::A> testAFoo<Type::B> testB也是如此。有人能告诉我我在这里可能做错了什么吗?此外,理想情况下,我希望定义类似于以下内容的全部专业:

代码语言:javascript
复制
template<isTypeA T>
struct Foo<T>
{
   Foo() { Print("Type A Foo"); }
};

但是上面的结果会产生编译器错误error: ‘isTypeA’ does not constrain a type。任何帮助都将不胜感激!

EN

回答 3

Stack Overflow用户

发布于 2022-03-02 06:50:06

std::is_enum不是一个概念,所以这个谓词不像我认为的那样:

代码语言:javascript
复制
template<std::is_enum T1, std::is_enum T2>
constexpr bool isEnumSame() { return T1 == T2; }

您可以直接获取Type值。此外,您的概念行需要调用如下函数:

代码语言:javascript
复制
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对任何枚举都是通用的:

代码语言:javascript
复制
template <class T>
concept Enumeration = std::is_enum_v<T>;

template<Enumeration auto T1, Enumeration auto T2>
constexpr bool isEnumSame() { return T1 == T2; }
票数 2
EN

Stack Overflow用户

发布于 2022-03-02 06:54:28

有几个问题:

  1. template is_enum是一个特征,而不是一个概念。您可以使用类似于auto T1的东西,然后使用requires std::is_enum_v<decltype(T1)>
  2. 模板概念isTypeA = isEnumSame;You forgot to call the function, add()`。

但你其实不需要任何这种概念魔法。您可以完全专门化枚举值的Foo

代码语言:javascript
复制
template <>
struct Foo<Type::A> {...};

如果您出于某些原因不希望完全专业化,可以这样做:

代码语言:javascript
复制
template <Type T>
requires (T == Type::A)
struct Foo<T> {...};
票数 1
EN

Stack Overflow用户

发布于 2022-03-02 06:56:11

首先,std::is_enum不是一个概念,它只是一个普通的类,所以像template<std::is_enum T1, std::is_enum T2>这样的语法只定义一个模板函数,它接受std::is_enum类型的非类型模板参数,这不是您所期望的,也不会约束任何东西。

其次,bool isEnumSame()的模板参数不是类型,而是枚举值,因此应该将其定义为template<auto T1, auto T2>

如果需要约束非类型模板参数的类型,则只需使用decltype获取其类型,并使用requires约束它,如下所示:

代码语言:javascript
复制
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>();

演示

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71318446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档