Search code examples
c++templatesdefault-arguments

Template class with default parameters used in another template class with access to default parameters


I am trying to put a template class into another (wrapper) template class while the first template class has a default parameter I need to use in the wrapper class. Here it is:

template <typename A, size_t B, typename C = size_t, bool D = true>
class MyClass;

This class can be used with only 2, 3 or 4 parameters given:

MyClass<int, char> object1;
MyClass<int, char, uint8_t> object2;
MyClass<int, char, uint8_t, false> object3;

The wrapper class shall be instantiated like this with any possible number of parameters for MyClass:

Wrapper<MyClass<uint8_t, 210>> firstWrapper;

but also

Wrapper<MyClass<uint8_t, 210, uint8_t>> secondWrapper;
Wrapper<MyClass<uint8_t, 210, uint8_t, false>> thirdWrapper;

The wrapper template class hence has a templated template parameter but here I need parameter C which is not always given directly. I tried these two implementations for the Wrapper class but none of them works:

Variant A:

// at least 2 parameters do not have a default value
template <template <typename, typename, typename...> class CONTAINER, typename A, typename B, typename... Ts>
class Wrapper<CONTAINER<A, B, Ts...>> {
private:
    CONTAINER<A, B, Ts...>& m_container;
    C m_index; //  < ---- How can I access the (default) parameter C 
}

Variant B:

template <template <typename, typename, typename, typename> class CONTAINER, typename A, typename B, typename C, typename D>
class Wrapper<CONTAINER<A, B, C, D>> {
private:
    CONTAINER<A, B, C, D>& m_container;
    C m_index; // works!
}

but with this variant I have to specify all 4 template parameters of MyClass and can't just use the default values for C and D.

How do I need to modify my Wrapper class so it can handle 2, 3 and 4 given template parameters of MyClass while I can still access the 3rd parameter's default value?


Solution

  • // primary template
    template <typename T>
    class Wrapper;
    
    // partial specialization
    template <template <typename, size_t, typename, bool> class CONTAINER, typename A, size_t B, typename C, bool D>
    class Wrapper<CONTAINER<A, B, C, D>>;
    

    Then you can

    // the default template arguments of MyClass will be used
    Wrapper<MyClass<uint8_t, 210>> firstWrapper;                 // A=uint8_t, B=210, C=size_t, D=true
    Wrapper<MyClass<uint8_t, 210, uint8_t>> secondWrapper;       // A=uint8_t, B=210, C=uint8_t, D=true
    Wrapper<MyClass<uint8_t, 210, uint8_t, false>> thirdWrapper; // A=uint8_t, B=210, C=uint8_t, D=false