如何简化C++特化模板类定义?避免通用函数重复实现
解决模板特化中的代码重复问题
问题场景
用户给出的代码通过模板特化区分默认可构造和不可构造的类型,但导致了构造函数和monomorphic函数的重复实现:
#include <iostream> #include <type_traits> template < typename T, bool B = std::is_default_constructible_v<T>> class toy_example; template<typename T> class toy_example<T, true> { public: toy_example() = default; // e.g. for default constructible types toy_example(const T& value); public: void monomorphic(T); private: T m_value; }; template<typename T> class toy_example<T, false> { public: toy_example() = delete; // e.g. for non-default constructible types toy_example(const T& value); // Repeated declaration public: void monomorphic(T); // Repeated declaration private: T m_value; }; // Implementation template<typename T> toy_example<T, true>::toy_example(const T& value) : m_value(value) {} // (Unnecessary?) Repetition template<typename T> toy_example<T, false>::toy_example(const T& value) : m_value(value) {} template<typename T> toy_example<T, true>::monomorphic(T) { std::cout << "Behaviour is the same despite specialisation.\n"; // (P.S) - This is intended behaviour } // (Unnecessary?) Repetition template<typename T> toy_example<T, false>::monomorphic(T) { std::cout << "Behaviour is the same despite specialisation.\n"; // (P.S) - This is intended behaviour }
用户需求:为行为一致的函数提供单一实现,避免代码重复,尤其针对冗长的monomorphic函数。
解决方案
方案1:提取共享基类(兼容C++11及以上)
将所有共享的成员变量、构造函数和函数实现提取到基类中,特化类仅处理差异部分(默认构造函数的启用/禁用):
#include <iostream> #include <type_traits> // 共享基类:集中所有重复逻辑 template <typename T> class toy_example_base { protected: T m_value; public: // 带参数的构造函数,仅实现一次 toy_example_base(const T& value) : m_value(value) {} // 共享的monomorphic函数,仅实现一次 void monomorphic(T) { std::cout << "Behaviour is the same despite specialisation.\n"; // 冗长的业务逻辑写在这里,无需重复 } }; // 主模板声明 template <typename T, bool B = std::is_default_constructible_v<T>> class toy_example; // 特化1:默认可构造类型 template <typename T> class toy_example<T, true> : public toy_example_base<T> { public: toy_example() = default; // 仅保留默认构造 using toy_example_base<T>::toy_example_base; // 继承基类的带参构造 }; // 特化2:不可默认构造类型 template <typename T> class toy_example<T, false> : public toy_example_base<T> { public: toy_example() = delete; // 仅删除默认构造 using toy_example_base<T>::toy_example_base; // 继承基类的带参构造 };
说明:
- 基类
toy_example_base集中了所有重复代码,避免特化类中的冗余实现。 - 特化类通过
using声明继承基类的构造函数,无需重复声明和实现。 - 仅在特化类中处理默认构造函数的差异,逻辑清晰。
方案2:利用C++20 requires子句(无需特化)
如果项目支持C++20,可以直接在单个类中用requires条件控制默认构造函数的可用性,彻底避免模板特化:
#include <iostream> #include <type_traits> template <typename T> class toy_example { public: // 仅当T可默认构造时,启用默认构造函数 toy_example() requires std::is_default_constructible_v<T> = default; // 否则删除默认构造函数 toy_example() requires (!std::is_default_constructible_v<T>) = delete; // 带参数的构造函数,仅实现一次 toy_example(const T& value) : m_value(value) {} // 共享的monomorphic函数,仅实现一次 void monomorphic(T) { std::cout << "Behaviour is the same despite specialisation.\n"; // 冗长的业务逻辑写在这里 } private: T m_value; };
说明:
- 无需拆分特化类,所有逻辑集中在一个模板类中,代码更紧凑。
- 通过
requires子句条件性启用/禁用默认构造函数,精准控制类型的构造行为。 - 完全消除了重复代码,适合现代C++项目。
内容的提问来源于stack exchange,提问作者buzzysin
相关产品推荐
相关产品推荐

