C++概念requires子句如何要求返回值的const版本满足指定约束
1
const LikeA auto &参数的概念校验规则 C++中约束自动推导的语法const LikeA auto &a,等价于如下模板声明:
template<LikeA T> void use(const T& a);
这里的const是参数的类型修饰符,作用于推导得到的类型T,而概念LikeA的校验对象是原始推导类型T,而非加了const修饰后的const T。
当你传入const A类型的实参时,模板参数T会被推导为A(参数的const T&会吸收实参的顶层const属性),此时仅需要校验LikeA<A>成立即可,自然可以正常编译。而static_assert(!LikeA<const A>)成立是因为const A类型无法调用非const成员函数modify,两者逻辑完全不冲突。
2 符合要求的
LikeAHolder实现方案 原来的写法失败的原因是:{t.getA() } -> LikeA的校验规则是验证LikeA<decltype((t.getA()))>成立,而decltype((t.getA()))是const A&,显然不满足LikeA约束。
你可以通过嵌套requires子句,对返回值类型做手动清洗后再校验,实现代码如下:
#include <type_traits> template<typename T> concept LikeAHolder = requires (T t) { { t.getA() }; // 清洗返回值的引用和顶层cv限定,校验原始类型满足LikeA requires LikeA<std::remove_cvref_t<decltype(t.getA())>>; }; static_assert(LikeAHolder<AHolder>); // 编译通过
该方案完全符合你的所有要求:
- 保留了完全的const正确性,
getA仍然返回const A&,不会允许外部修改holder内部的私有成员 - 没有对外暴露额外的独立概念,所有类型清洗逻辑都封装在
LikeAHolder的定义内部,终端用户仅需要感知LikeA和LikeAHolder两个公开概念即可 - 完全没有修改原有
LikeA的校验逻辑,LikeA<const A>的判定结果仍然为false,不会破坏原有概念语义
内容的提问来源于stack exchange,提问作者Maximilian Keßler
相关产品推荐
相关产品推荐

