用c++模板编译类成员变量

Compiling Class Member Variables Out with C++ Templates?

本文关键字:成员 变量 编译 c++      更新时间:2023-10-16

我有一个类,看起来像这样:

class Compound
{
    void* pValue0;
    void* pValue1;
    void* pValue2;
    void* pValue3;
    void* pValue4;
    void* pValue5;
    void* pValue6;
    void* pValue7;
    void* pValue8;
    void* pValue9;
    void* pValueA;
    void* pValueB;
    void* pValueC;
};

当我创建一个新的复合类,我分配额外的内存[sizeof(Compound) + extraSpace]。每个pValue都指向额外内存中的一个地址。

现在,我想根据需要减少pValue的数量。模板看起来很合适。

所以如果我想要一个类Compound<0A>,我只需要pValue0和pValueA,然后让编译器删除所有其他的pvalue。本质上,我希望它变成:

template <uint Mask = 0A>
class Compound<Mask>
{
    void* pValue0;
    void* pValueA;
}

这可能吗?我接近了enable_if,但是当我试图将其限制为特定的掩码时,当enable_if大小写为false时,编译器会抛出关于无法找到类型的错误。

谢谢大家!

可以这样做:

template<char...>
struct flags_tag {constexpr flags_tag(){}; };
template<char...Cs>
struct make_flags{ using type=flags_tag<Cs...>; };
template<char...Cs>
struct make_flags<'0','x',Cs...>:make_flags<Cs...>{};
template<char...Cs>
struct make_flags<'0','X',Cs...>:make_flags<Cs...>{};
template<char...Cs>
using make_flags_t = typename make_flags<Cs...>::type;
template<char...Cs>
constexpr make_flags_t<Cs...> operator""_flag(){ return {}; }
template<char> struct pValue_t;
template<> struct pValue_t<'0'>{ void* pValue0 = 0; };
template<> struct pValue_t<'1'>{ void* pValue1 = 0; };
// ...
template<> struct pValue_t<'A'>{ void* pValueA = 0; };
template<> struct pValue_t<'B'>{ void* pValueB = 0; };
template<> struct pValue_t<'C'>{ void* pValueC = 0; };
template<class flags>
struct Compound;
template<char...Cs>
struct Compound< flags_tag<Cs...> >:
  pValue_t<Cs>...
{};

然后像这样使用:

using my_type = Compound< decltype( 0x0A_flag ) >;
int main() {
  my_type test;
  std::cout << test.pValue0 << test.pValueA << 'n';
}

似乎做你想做的。

我还会禁用Compound类型的复制/移动函数,并使其其他构造函数private具有friend工厂功能。

请注意,这段代码可以生成指数数量的类(2^12,或4k),这可能导致二进制膨胀(如果任何每个类的代码没有内联而不存在)。

(生活例子)

std::conditional类似于std::enable_if,除了条件总是返回一个类型。

std::conditional<satisfies(Mask), void*, EmptyClass>将是有条件地交换成员类型并使其编译的方法。

问题是,c++不允许空成员。大小为1。要解决这个问题,需要使用空成员优化。这将实现您所要求的内存布局,但不幸的是,这将使类成员难以阅读。如果您认为值得这样做,可以添加访问器函数来缓解这种情况。

我假设Compound类应该包含指向不同类的对象的指针,而不是void指针,正如你在评论中所说的。

我不知道这是不是一个好主意,因为我认为在设计中有一些错误,但你可以在ints上使用元组和模板专门化来选择你想要的类型:

class Class0;
class ClassA;
template<int> struct Compound {};
template<> struct Compound<0A> 
{
    typedef std::tuple<Class0*, ClassA*> type;
}
// other mapping from mask to type
typename Compound<0A>::type aCompund(ptr0, ptrA);