我对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。任何帮助都将不胜感激!
发布于 2022-03-02 06:50:06
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; }发布于 2022-03-02 06:54:28
有几个问题:
is_enum是一个特征,而不是一个概念。您可以使用类似于auto T1的东西,然后使用requires std::is_enum_v<decltype(T1)>。You forgot to call the function, add()`。但你其实不需要任何这种概念魔法。您可以完全专门化枚举值的Foo:
template <>
struct Foo<Type::A> {...};如果您出于某些原因不希望完全专业化,可以这样做:
template <Type T>
requires (T == Type::A)
struct Foo<T> {...};发布于 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约束它,如下所示:
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://stackoverflow.com/questions/71318446
复制相似问题