如何在派生类中以最少样板代码使用static constexpr属性
问题
如何在Derived类中编写最少的样板代码,使其能够访问Base类的static constexpr属性?核心目标是移除Derived中重复冗长的样板代码(比如多次复制粘贴长达200字符的Base模板实例化参数)。
最小可运行示例
#include <iostream> #include <array> // Base类用于为Derived类批量定义static constexpr属性,减少重复代码 template<size_t n_, std::array<const size_t,n_> a_> // 实际场景中还有更多模板参数 class Base{ public: static constexpr size_t n = n_; static constexpr std::array<const size_t,n_> a = a_; // static constexpr std::array<const size_t,n_> b = static_sum_over_static_array<const size_t>(a); // ... 还有更多复杂的static constexpr属性定义 static constexpr size_t get_n(){ return n; } }; class Derived: public Base<10,{3,5,6,7,2,0,1,4,2,9}>{ // 冗余样板代码:每次都要重复写完整的Base实例化参数 using Base<10,{3,5,6,7,2,0,1,4,2,9}>::n; using Base<10,{3,5,6,7,2,0,1,4,2,9}>::a; // using Base<10,{3,5,6,7,2,0,1,4,2,9}>::b; // 这类using声明会产生大量重复代码 // 业务代码:需要直接访问基类的属性 int x[n]; // 不希望用这种方式:既冗余又可读性差 int y[get_n()]; }; int main() { Derived b; }
实际场景中,Base的单个实例化模板参数文本长度平均约200字符,重复编写会极大降低代码可维护性。Base类的设计初衷就是为Derived类提供便捷的静态属性构建块,若需要编写大量样板代码,Base的存在就失去了意义。同时,普通宏无法解决该问题(会导致重复编写模板参数)。
解决方案
方案1:为基类定义别名(推荐)
在Derived内部为继承的Base实例定义一个简短别名,后续所有using声明都通过别名引用,避免重复编写冗长的模板参数:
#include <iostream> #include <array> template<size_t n_, std::array<const size_t,n_> a_> class Base{ public: static constexpr size_t n = n_; static constexpr std::array<const size_t,n_> a = a_; static constexpr size_t get_n(){ return n; } }; class Derived: public Base<10,{3,5,6,7,2,0,1,4,2,9}>{ // 仅需编写一次完整的Base实例化参数 using BaseType = Base<10,{3,5,6,7,2,0,1,4,2,9}>; // 通过别名引用基类成员,简洁且无重复 using BaseType::n; using BaseType::a; // using BaseType::b; // 其他需要的属性同理 // 业务代码保持简洁 int x[n]; }; int main() { Derived b; }
该方案完全避免了重复编写长模板参数,仅需一次定义别名,后续的using声明都非常简洁,对代码可读性影响极小。
方案2:使用宏批量生成样板代码
如果需要创建多个类似的Derived类,可以用宏封装继承和别名定义,进一步减少重复工作:
#include <iostream> #include <array> template<size_t n_, std::array<const size_t,n_> a_> class Base{ public: static constexpr size_t n = n_; static constexpr std::array<const size_t,n_> a = a_; static constexpr size_t get_n(){ return n; } }; // 宏定义:自动生成基类继承、别名和常用成员的using声明 #define CREATE_DERIVED(CLASS_NAME, BASE_INSTANCE) \ class CLASS_NAME: public BASE_INSTANCE { \ using BaseType = BASE_INSTANCE; \ using BaseType::n; \ using BaseType::a; \ // 可根据需要添加更多默认的using声明 // 创建Derived类 CREATE_DERIVED(Derived, Base<10,{3,5,6,7,2,0,1,4,2,9}>) { // 业务代码 int x[n]; }; int main() { Derived b; }
该方案适合需要创建多个Derived类的场景,宏会自动处理样板代码,只需专注于业务逻辑部分。
说明
Derived类属于业务代码,实际会被实例化约5次,每次基于Base提供的静态属性构建个性化应用,并非作为基类使用,因此不存在不良设计问题。
内容的提问来源于stack exchange,提问作者kaisong
相关产品推荐
相关产品推荐

