更改派生类的模板参数

发布于 2024-12-25 16:58:08 字数 1190 浏览 1 评论 0原文

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

这是通过每次创建 C 实例(在 main 方法中)时手动编写代码来完成的。有没有办法将此功能移至 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 为 T 定义了类型 T<2>

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

  • 添加更多模板魔法...

In the code below, C's base class B1's template argument OFFSET depends on B0, and B2 on B1.

This is done by manual write the code every time an instance of C is created (in the main method). Is there a way to move this functionality to the definition of C instead?

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;
}

EDIT:

To answer the comments, here are the steps I think needs to be taken to solve this:

  • Write a metafunction which can change the offset:
    set_new_offset which for T defines the type T<2>

  • Use boost::mpl::times to calculate the new offsets

  • Add more template magic...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

潦草背影 2025-01-01 16:58:08

你可以用 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;
}

You can do it with template templates in C, although I'm not 100% sold it's an improvement. If you only ever need three bases this should be fine. If you need an arbitrary number of bases...there must be a better way to do this than inheritance as this method will get unwieldy.

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;
}
时光无声 2025-01-01 16:58:08

定义一个辅助类怎么样:

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 左右...)

How about defining a helper class:

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

Then you can say:

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

If necessary one could think up a higher-order composer that allows you to form higher "powers" of composition.

(Maybe Composer should have been called Bind1st or so...)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文