如何避免类模板特化导致的代码重复?C++技术求助
嘿,我懂你现在的困扰——这三个几乎一模一样的FooClass特化确实太冗余了!你说得没错,用enable_if加上类型萃取就能完美解决,不用再重复写三段几乎相同的代码。下面直接上解决方案,再给你拆解关键逻辑:
优化后的代码
#include <iostream> #include <type_traits> struct Bar{}; template <class... Args> struct FooClass; // 用偏特化+SFINAE替代三个重复的全特化 template <class T> struct FooClass<T, std::enable_if_t<std::is_same_v<std::remove_cvref_t<T>, Bar>>> { inline static void impl(const Bar& b) { // 编译时判断传入类型,输出对应内容(如果不需要区分可直接写统一逻辑) if constexpr (std::is_const_v<std::remove_reference_t<T>>) { std::cout << "dup1" << std::endl; } else if constexpr (std::is_rvalue_reference_v<T&&>) { std::cout << "dup2" << std::endl; } else { std::cout << "dup3" << std::endl; } } }; template <class... Args> inline void foo(Args&&... args) { FooClass<Args...>::impl(std::forward<Args>(args)...); } int main() { const Bar b2; foo(b2); // 输出dup1 foo(Bar{}); // 输出dup2 Bar b; foo(b); // 输出dup3 }
关键逻辑拆解
统一匹配所有Bar相关类型
用std::remove_cvref_t<T>可以移除类型的const/volatile修饰符和引用,所以不管T是Bar、Bar&还是const Bar&,std::remove_cvref_t<T>最终都是Bar。再通过std::is_same_v配合std::enable_if_t做约束,确保这个偏特化只匹配和Bar相关的类型,不会干扰其他可能的特化。编译时分发不同逻辑
示例里需要区分三种情况输出不同内容,用C++17的if constexpr可以在编译时判断传入的T的具体属性:std::is_const_v<std::remove_reference_t<T>>:判断是否是const引用类型std::is_rvalue_reference_v<T&&>:判断是否是右值(临时对象)- 剩下的就是非const左值引用类型
如果不需要区分输出,直接把impl里的逻辑统一成一段即可,完全消除重复。
覆盖原有的三种特化场景
原来的三个全特化分别对应foo传入const Bar&、Bar(右值)、Bar&时推导出来的Args类型,现在这个偏特化会匹配所有这三种情况,所以注释掉原来的任何特化都不会导致编译失败。
内容的提问来源于stack exchange,提问作者B0rk4
相关产品推荐
相关产品推荐

