Search code examples
c++classc++17if-constexpr

Conditionally creating members inside a class


Is it possible to do something like:

template <unsigned majorVer, unsigned minorVer>
class Object
{
public:

    if constexpr ((majorVer == 1) && (minorVer > 10))
        bool newField;
    else
        int newInt
};

or

template <unsigned majorVer, unsigned minorVer>
class Object
{
public:

    if constexpr ((majorVer == 1) && (minorVer > 10))
        bool newField;
    // Nothing other wise
};

using c++17? I would like to change the structure of a class based on some condition that can be checked at compile time. Is there any way to achieve this?


Solution

  • You can't use if constexpr for this. You would have to collapse them into one member using something like std::conditional:

    std::conditional_t<(majorVer == 1) && (minorVer > 10), bool, int> newField;
    

    Alternatively, you can wrap each of the two kinds of the fields in their own type:

    struct A { bool newField; };
    struct B { int newInt; };
    

    And either inherit from std::conditional_t<???, A, B> or have one of those as a member.


    For the case where you want either a member or nothing, the other case just needs to be an empty type. In C++20, that's:

    struct E { };
    [[no_unique_address]] std::conditional_t<some_condition(), bool, E> newField;
    

    In C++17 and earlier, you'll want to inherit from this to ensure that the empty base optimization kicks in:

    struct B { bool field; };
    struct E { };
    
    template <unsigned majorVer, unsigned minorVer>
    class Object : private std::conditional_t<some_condition(), B, E>
    { ... };