能否传递C++ Concept本身?如何像传递模板一样传递Concept?
先看以下代码定义:
template<class S> using Floating1 = std::is_floating_point<S>; template<class S> concept Floating2 = std::is_floating_point_v<S>;
我们可以将Floating1作为模板模板参数传递给TType,示例如下:
template<template<class...> class F> struct TType { template<class... S> using type = F<S...>; }; using X = TType<Floating1>; //... template<class S> using Y = typename X::template type<S>;
现在的疑问是:Floating2该如何处理?我们可以像实例化Floating1<S>那样,通过函数重载区分Floating2的满足情况,但怎样才能像传递Floating1给TType那样传递Floating2?
我怀疑这无法实现,就像无法直接传递class或auto一样。
以std::invoke这类函数为例,它们有指定返回类型的变体,要是返回类型能是带约束的auto就好了。除了在concept/约束自身内部,有没有函数、模板等可以接收concept?
或者我们可以为每个要使用的concept编写两个辅助函数(一个用concept,一个不用),但肯定有更好的方法。
为什么无法直接传递Concept给模板模板参数
C++的Concept是约束实体,而模板模板参数要求的是模板(类模板、变量模板、别名模板),二者属于不同的语法范畴,所以无法直接把Floating2这种Concept传递给TType这类接收模板模板参数的模板——就像你怀疑的那样,这和无法直接传递class或auto是一个道理。
替代方案:将Concept包装为模板
如果想要让Concept能适配模板模板参数的场景,可以把它包装成一个类型模板别名或者类模板,模拟Floating1的形式:
方案1:包装为类型模板别名
利用std::bool_constant把Concept的结果转换成类型:
template<class S> using Floating2Wrapper = std::bool_constant<Floating2<S>>;
这样Floating2Wrapper就可以像Floating1一样传递给TType了:
using X2 = TType<Floating2Wrapper>; template<class S> using Y2 = typename X2::template type<S>;
方案2:包装为类模板
如果需要更灵活的扩展,可以手动编写类模板:
template<class S> struct Floating2WrapperStruct { static constexpr bool value = Floating2<S>; };
同样可以传递给TType:
using X3 = TType<Floating2WrapperStruct>; template<class S> using Y3 = typename X3::template type<S>;
针对函数场景的替代方案
如果是在函数中需要接收Concept相关的逻辑,不需要传递Concept本身,而是可以直接利用Concept做重载约束,或者用requires子句限定模板:
// 直接用Concept约束函数模板 template<Floating2 S> void process(S val) { // 处理浮点类型 } // 或者用requires子句 template<class S> requires Floating2<S> void process(S val) { // 处理浮点类型 }
如果需要在函数中动态判断类型是否满足Concept,也可以直接用Floating2<S>作为常量表达式使用:
template<class S> void check(S val) { if constexpr (Floating2<S>) { // 浮点类型分支 } else { // 非浮点类型分支 } }
关于接收Concept的模板/函数
C++标准中,除了在约束上下文(比如requires子句、Concept定义、模板参数约束)中,没有直接接收Concept作为参数的语法。Concept本质是编译期的布尔谓词,我们通常是通过它的实例化结果(Floating2<S>的布尔值)来使用,而非传递Concept本身。
内容的提问来源于stack exchange,提问作者John P

