如何编写C++ Concept以要求函数模板需传入枚举值作为模板参数?
问题解答
需求可行性
完全可行,借助C++20的Concept特性可以实现对这类类型的约束。
现有实现的问题分析
第一种实现的错误原因
你尝试用约束变量n作为模板参数,但n是运行时变量,而模板参数要求必须是编译期常量,因此编译器报错“Constraint variable 'n' cannot be used in an evaluated context”,这是C++模板参数的基本规则限制。
第二种实现的错误原因
std::declval<notification_t>()返回的是notification_t类型的右值对象,但notifiable_type::notification的模板参数是枚举值(非类型参数),而非枚举类型。你这里相当于把类型当作模板参数传递,与目标函数模板的参数要求不匹配,因此约束不满足。
正确的Concept实现
#include <concepts> #include <type_traits> enum class categories { t1, t2 }; struct notifiable_type { template<categories category> auto notification() {} }; template<typename NotifiableT, typename EnumT> concept Notifiable = std::is_enum_v<EnumT> && requires(NotifiableT t) { // 验证存在以EnumT枚举值为模板参数的notification成员函数,且返回void template<EnumT E> { t.template notification<E>(); } -> std::same_as<void>; }; // 验证约束生效 static_assert(Notifiable<notifiable_type, categories>); auto main() -> int { notifiable_type().notification<categories::t1>(); return 0; }
实现说明
- 用
std::is_enum_v<EnumT>确保第二个模板参数是枚举类型; - 在
requires表达式中使用模板化的约束子句,声明一个类型为EnumT的非类型模板参数E; - 检查调用
t.template notification<E>()是否合法,且返回值类型为void,以此验证目标类型拥有符合要求的成员函数模板。
内容的提问来源于stack exchange,提问作者David Spry
相关产品推荐
相关产品推荐

