更改派生类的模板参数

Changing the template arguments of derived classes

本文关键字:参数 派生      更新时间:2023-10-16

在下面的代码中,C的基类B1的模板参数OFFSET依赖于B0,B2依赖于B1。

这是通过每次创建C实例时手动编写代码来完成的(在主方法中)。有没有办法将这个功能转移到C的定义中?

template<int OFFSET>
struct A {
    enum O { offset = OFFSET };
    enum S { size = 2 };
};
template<int OFFSET>
struct B {
    enum O { offset = OFFSET };
    enum S { size = 4 };
};
template < typename B0, typename B1, typename B2 >
struct C : public B0, B1, B2 {
};
int main(int argc, const char *argv[])
{
    // instance of C
    C< A<1>,
       B< A<1>::offset * A<1>::size >,
       A<
           B< A<1>::offset * A<1>::size >::offset *
           B< A<1>::offset * A<1>::size >::size
       >
    > c1;
    // does the same thing
    C< A<1>,
       B< A<1>::size >,
       A<
           A<1>::size *
           B< A<1>::size >::size
       >
    > c2;
    return 0;
}

编辑:

为了回答这些评论,我认为需要采取以下步骤来解决这个问题:

  • 编写一个可以更改偏移量的元函数:set_ new_ offset;2>

  • 使用boost::mpl::times计算新偏移

  • 添加更多模板魔术。。。

您可以使用C中的模板模板来实现这一点,尽管我不是100%相信这是一个改进。如果你只需要三个垒,这应该没问题。如果你需要任意数量的基数。。。必须有比继承更好的方法来做到这一点,因为这种方法会变得笨拙。

template<int OFFSET>
struct A {
    enum O { offset = OFFSET };
    enum S { size = 2 };
};
template<int OFFSET>
struct B {
    enum O { offset = OFFSET };
    enum S { size = 4 };
};
template < typename B0, template <int T> class B1, template <int T> class B2 >
struct C : public B0, B1<B0::offset * B0::size>, B2<B1<B0::offset * B0::size>::offset * B1<B0::offset * B0::size>::size> {
    enum
    {
        B0_offset = B0::offset,
        B1_offset = B1<B0::offset * B0::size>::offset,
        B2_offset = B2<B1<B0::offset * B0::size>::offset * B1<B0::offset * B0::size>::size>::offset,
        B0_size = B0::size,
        B1_size = B1<B0::offset * B0::size>::size,
        B2_size = B2<B1<B0::offset * B0::size>::offset * B1<B0::offset * B0::size>::size>::size
    };
};
int main()
{
    // instance of C
    C< A<1>,
       B,
       A
    > c1;
    static_cast<void>(c1);
    // does the same thing
    C< A<1>,
       B,
       A
    > c2;
    static_cast<void>(c2);
    std::cout << c1.B0_offset << std::endl;
    std::cout << c1.B1_offset << std::endl;
    std::cout << c1.B2_offset << std::endl;
    std::cout << c1.B0_size << std::endl;
    std::cout << c1.B1_size << std::endl;
    std::cout << c1.B2_size << std::endl;
    std::cout << c2.B0_offset << std::endl;
    std::cout << c2.B1_offset << std::endl;
    std::cout << c2.B2_offset << std::endl;
    std::cout << c2.B0_size << std::endl;
    std::cout << c2.B1_size << std::endl;
    std::cout << c2.B2_size << std::endl;
    return 0;
}

如何定义一个辅助类:

template <template <int> class C, int N>
struct Composer
{
    enum O { offset = C<N>::offset * C<N>::size; };
    enum S { size = C<N>::size; };
};

然后你可以说:

C<A<1>, Composer<A, 1>, Composer<B, Composer<A, 1>::offset> c2;

如果有必要,可以想出一个更高阶的作曲家,让你形成更高的"力量"。

(也许Composer应该被称为Bind1st左右…)