Compile group member variables with C ++ templates?

advertisements

I have a class that looks similar to this:

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

When I create a new Compound class, I allocate extra memory [sizeof(Compound) + extraSpace]. Each of the pValue's refer to an address in the extra memory.

Now, I would like to reduce the number of pValue's depending on which of them I need. Templates seem like a good fit.

So if I wanted a class Compound<0A>, I would only want pValue0 and pValueA, and then have the compiler remove all other pValues. Essentially, I would want it to then become:

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

Is this possible? I got close with enable_if, but when I tried to limit it to a particular mask the compiler threw errors about being unable to find a type when the enable_if case was false.

Thank you all!


This might do:

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

Then you use it like:

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

which seems to do what you want.

I'd also disable the copy/move ctor of your Compound type, and make its other constructors private with a friend factory function.

Note that this code can generate an exponential number of classes (2^12, or 4k), and that can cause binary bloat (if any per-class code isn't inlined out of existence).

[live example]