如何要求表达式结果可转换/衰退为满足指定concept的类型?
解决方案:无需重复定义专用Concept
不需要为每个目标Concept创建诸如ConvertibleToFloatingPoint这类半重复的概念,利用C++20的模板Concept组合能力,就能简洁实现需求。
1. 要求表达式结果可转换到满足某Concept的类型
可以定义一个通用的converts_to_concept模板Concept,它能适配任意目标Concept(不管是标准库的还是自定义的):
#include <type_traits> template<typename ExprResult, template<typename> typename Concept> concept converts_to_concept = requires(ExprResult&& val) { // 通过模板lambda推导,验证存在满足Concept的类型To,且ExprResult可转换为To []<typename To>(std::type_identity_t<To>) requires Concept<To> {}(std::forward<ExprResult>(val)); }; // 使用示例:要求t.bar的结果能转换到任意满足std::floating_point的类型 template<typename T> concept HasBar = requires(T t) { { t.bar } -> converts_to_concept<std::floating_point>; }; // 自定义Concept也能直接复用 template<typename T> concept MyConcept = requires(T t) { t.foo(); }; template<typename T> concept HasBarConvertibleToMyConcept = requires(T t) { { t.bar } -> converts_to_concept<MyConcept>; };
2. 要求表达式结果衰退后满足某Concept的类型
这种场景更简单,直接对表达式结果的衰退类型做Concept检查即可,也可以封装成通用模板简化复用:
#include <type_traits> // 通用衰退检查Concept template<typename ExprResult, template<typename> typename Concept> concept decays_to_concept = Concept<std::decay_t<ExprResult>>; // 使用示例:要求t.bar衰退后是整数类型 template<typename T> concept HasBarDecaysToIntegral = requires(T t) { { t.bar } -> decays_to_concept<std::integral>; }; // 也可以直接写在requires里,更直观 template<typename T> concept HasBar = requires(T t) { requires std::floating_point<std::decay_t<decltype(t.bar)>>; };
核心思路
通用模板Concept的优势在于一次定义,就能适配所有目标Concept,避免了重复编写相似逻辑的冗余代码,同时保持代码的可读性和简洁性。不管是标准库提供的std::floating_point、std::integral,还是自定义的MyConcept,都能直接套用这些通用模板。
内容的提问来源于stack exchange,提问作者Newline
相关产品推荐
相关产品推荐

