可变模板——从另一个类生成一个c++类

variadic templates - Generate a C++ class from an other one

本文关键字:c++ 一个 另一个      更新时间:2023-10-16

我想从class X生成class Y:

class X{
  T e;
  optional<T1> e1;
  optional<T2> e2;
  optional<T3> e3;
  T4 e4;
  // Member functions
  ...
};
class Y{ 
  T  e;
  T1 e1;
  T2 e2;
  T3 e3;
  T4 e4;
  bool b1;
  bool b2;
  bool b3;
  // Member functions
  ...
}

所以,基本上我想把可选的布尔值放在最后来赢得一些内存,(这被称为打包)你可以假设成员函数不使用任何可选的,所以生成的代码将是正确的,而且类可以有尽可能多的可选

我知道c++中没有类反射,但是使用可变模板,似乎我们可以做一些很棒的事情。

我一直在想用它们来解决这个问题,但是我找不到任何解决方案。我想别人可能也做过这样的事。

编辑:

这样做的主要目标是减少第一个类的内存,通过将可选的布尔值放在最后(减少填充),派生不会这样做,因为derived classsize将大于base class

代码可以通过将类X作为模板传递给生成器ClassGenerator<X>来生成,或者生成器可以接受像这样的更多参数ClassGenerator<X, T1, T2, T3>

基本上,我想把optional的布尔值放在最后来赢得一些内存,

回收内存的最好方法是将它们声明为位域,或者手动执行等效的按位算术。

这个问题可以通过使用可变模板和按位算术来解决。要聚合成员可以使用std::tuple,聚合位可以使用std::bitset。从这里,您可以创建一个按值返回optional的访问器。

可以假设成员函数不使用任何可选函数,因此生成的代码将是正确的

没有成员函数

你可能高估了c++在类型转换方面给你的自由。例如,不能将X*转换为Y*。不可能。(至少,如果您使用Y*结果,则不会。)


真的,困难的部分是你没有optional了,你需要重新发明它。所以你需要某种形式的联盟,但单独的联盟不知道如何移动或摧毁自己,因为他们需要这一点。所以你不能把它们放在tuple中,所以你也需要重新设计tuple

template< typename t >
union storage {
    t value;
    storage() {} // uninitialized
    storage( t in ) : value( std::move( in ) ) {}
    // Impossible to define the copy/move constructor.
    ~ storage() // Impossible to define. Destroy value or not?
};
template< typename ... elem >
class optional_tuple {
    std::tuple< storage< elem > ... > e
    std::bitset< sizeof ... (elem) > b;
    optional_tuple( std::optional< elem > ... v )
        : e{ std::move( v ) ... }
        , b{ (bool) v ... }
        {}
    }
};