如何在使用最小样板派生中使用静态 constexpr 属性?

How to use static constexpr attributes in derived with minimum boilerplate?

提问人:kaisong 提问时间:10/28/2023 更新时间:10/28/2023 访问量:31

问:

问题

中最小的样板代码是什么,以便可以访问静态 constexpr 属性?DerivedDerivedBase

问题的重点是从 中删除样板。Derived

最小工作示例

#include <iostream>
#include <array>

// Base only exists to remove boilerplate from Derived in defining a plethora of static constexpr attributes
template<size_t n_, std::array<const size_t,n_> a_> // ... and many more template arguments for Base
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);
    // ... and many more non-trivial static constexpr attributes are defined here

    // trading one line less in Derived for hundred lines more in Base is fine
    static constexpr size_t get_n(){ return n; }
};

class Derived: public Base<10,{3,5,6,7,2,0,1,4,2,9}>{
    
    // boilerplate
    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; 
    // these lines with the "using" create an incredible amount of boilerplate
    
    // compact user code
    int x[n]; // I need to access the parent attributes

    // undesirable (boilderplate + unreadable)
    int y[get_n()];
};

int main() {
    Derived b;
}

由于这是堆栈溢出要求的最小示例,因此指定 Base 实现的文本长度平均为 ~200 个字符这一事实仍然没有表示。

Base 存在的原因是,可以实现像 Derived 这样的类,这些类使用 Base 中的静态 constexpr 属性来创建 Derived 属性,如示例中所示。x

如果我必须写 30 行样板行,那实际上是没有用的。此外,似乎没有办法用宏隐藏样板,因为这反过来又需要再次编写 Base 的实现模板参数两次(一次在继承声明中,一次在宏调用中),我想不惜一切代价避免这种情况。Derived

言论

对一长串静态常量表达式的需求使它看起来像是一个超类,这是不好的做法。外观是错误的,客户代码也是如此,他们用 Base 的属性(可能是 30 个中的 10 个,但每次都不同)实例化 ~5 个对象,以从方便的构建块定义单个用户应用程序。DerivedDerived

C++ 继承 样板

评论

1赞 user17732522 10/28/2023
您根本不需要声明。没有它们,它也能工作。只是正确的。此外,从技术上讲,不允许将 braced-init-lists 作为模板参数。无论如何,它只是 GCC 允许它(可以说这是标准的缺陷,它不允许)。usingint x[n];
1赞 user17732522 10/28/2023
也许你的意思也是一个模板,它的基础是依赖的?在这种情况下,您所要做的就是使成员的名称从属,以便查找延迟到实例化,例如 .Derivedint x[Derived::n];
0赞 kaisong 10/29/2023
@user17732522。了不起。这是超级有用的。我没想到会这样,所以我甚至没有尝试过。是的,完全解决了我的问题。现在 Derived 和 Base 确实依赖于其他相互模板,但我只是在没有这些依赖关系的情况下创建另一个 Base,并且只是将所有样板转移到那里。伟大。非常感谢!

答: 暂无答案