使用非类型模板参数的 C++20 概念对类模板进行完全专业化
我对 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
和 Foo
template<isTypeA T>
struct Foo<T>
{
Foo() { Print("Type A Foo"); }
};
但上面会产生编译器错误 error: 'isTypeA' does not constrain a type
。任何帮助将不胜感激!
I am fairly new to C++20 Concepts and I am experimenting with creating a template class Foo
with fully specialised implementations based on a non-type (enumerator) template parameter. I have tested my idea using the code below:
// 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;
}
However, I get compiler errors like the following (I'm using g++11 and gcc11):
error: insufficient contextual information to determine type
27 | Foo<Type::C> testC;
and similarly for Foo<Type::A> testA
and Foo<Type::B> testB
. Can someone advise me on what I may be doing incorrectly here? Also, I would ideally like to define the full specialisations similar to:
template<isTypeA T>
struct Foo<T>
{
Foo() { Print("Type A Foo"); }
};
but the above yields the compiler error error: ‘isTypeA’ does not constrain a type
. Any help would be much appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
std::is_enum
不是一个概念,因此这个谓词不会执行我认为您认为它会执行的操作:您可以直接获取
Type
值。另外,您的概念行需要像这样调用函数:如果您希望
isEnumSame
对任何枚举都是通用的:std::is_enum
is not a concept, so this predicate does not do what I assume you think it does:You can take
Type
values directly. Also, your concept lines need to call the functions like so:If you want your
isEnumSame
to be generic over any enumeration:有几个问题:
is_enum
是一个特征,而不是一个概念。您可以使用诸如auto T1
之类的东西,然后requires std::is_enum_v
。您忘记调用该函数,请添加
()
。但你实际上并不需要任何这种概念魔法。您可以完全专门化
Foo
来获取枚举值:如果您出于某种原因不想完全专门化,您可以这样做:
There are several problems:
is_enum
is a trait, not a concept. You can use something likeauto T1
, and thenrequires std::is_enum_v<decltype(T1)>
.You forgot to call the function, add
()
.But you don't actually need any of this concept magic. You can fully specialize
Foo
for the enum values:If you for some reason don't want a full specialization, you can do this:
首先,
std::is_enum
不是一个概念,它只是一个普通的类,因此像
template
这样的语法只是定义一个接受std::is_enum
,这不是您所期望的,并且不限制任何内容。其次,
bool isEnumSame()
的模板参数不是类型,而是枚举值,因此应该定义为template。
。如果需要约束非类型模板参数的类型,可以使用 decltype 来获取其类型,然后使用 requires 表达式来约束它,如下所示:
演示
First,
std::is_enum
is not a concept, it is just a normal class,so a syntax like
template<std::is_enum T1, std::is_enum T2>
just defines a template function that accepts a non-type template parameter of typestd::is_enum
, which is not what you might expect and doesn't constrain anything.Second, the template parameter of
bool isEnumSame()
is not a type but a enum value, so it should be defined astemplate<auto T1, auto T2>
.If you need to constrain the type of the non-type template parameter, you can just use
decltype
to get its type and use requires-expression to constrain it, like this:Demo