如何通过C++概念去除类型修饰,限定函数参数为指定类型变体?
实现方案
当然可以实现,核心思路是逐层剥离类型的引用、CV限定符和指针属性,最终判断底层类型是否为Foo。下面提供两种可行的实现方式:
方法1:自定义plainify类型特征
先实现一个递归的类型特征plainify,用来逐层移除引用、CV限定和指针:
#include <type_traits> struct Foo {}; // 递归处理CV和引用 template<typename T> struct plainify { using type = typename plainify<std::remove_cvref_t<T>>::type; }; // 特化处理指针类型,递归剥离指针 template<typename T> struct plainify<T*> { using type = typename plainify<T>::type; }; // 终止条件:非指针、非CV引用的原始类型 template<typename T> struct plainify<T> { using type = T; }; // 别名模板简化使用 template<typename T> using plainify_t = typename plainify<T>::type; // 定义概念 template<typename T> concept Foo_C = std::is_same_v<Foo, plainify_t<T>>; // 受限的passFoo函数 template<Foo_C Foo_c> void passFoo(Foo_c foo) {}
方法2:直接在Concept中递归判断(更简洁)
不需要单独定义类型特征,直接在Concept内部通过constexpr递归逻辑完成判断:
#include <type_traits> struct Foo {}; template<typename T> concept Foo_C = []{ using U = std::remove_cvref_t<T>; if constexpr (std::is_pointer_v<U>) { // 递归处理指针指向的类型 return Foo_C<std::remove_pointer_t<U>>; } else { // 最终判断是否为Foo return std::is_same_v<U, Foo>; } }(); template<Foo_C Foo_c> void passFoo(Foo_c foo) {}
测试与调整
上面的代码默认支持多层指针(比如Foo**),如果只需要支持单层指针(拒绝Foo**),可以修改Concept的逻辑:
template<typename T> concept Foo_C = []{ using U = std::remove_cvref_t<T>; if constexpr (std::is_pointer_v<U>) { // 仅处理一层指针,直接判断指向的类型是否为Foo return std::is_same_v<std::remove_cvref_t<std::remove_pointer_t<U>>, Foo>; } else { return std::is_same_v<U, Foo>; } }();
测试用例(合法调用):
int main() { Foo f; const Foo cf; Foo& rf = f; const Foo& crf = cf; Foo* pf = &f; const Foo* cpf = &cf; passFoo(f); // 合法 passFoo(cf); // 合法 passFoo(rf); // 合法 passFoo(crf); // 合法 passFoo(pf); // 合法 passFoo(cpf); // 合法 // int x; // passFoo(x); // 编译错误,不符合Foo_C概念 return 0; }
内容的提问来源于stack exchange,提问作者TwistedBlizzard
相关产品推荐
相关产品推荐

