Search code examples
c++templatesavr-gcc

Class template with multiple parameters and default parameter


I've a class template like that:

struct Relay
{
    int pin;
    bool state;
};

template<std::size_t N, uint8_t D = 10>
class RelayArray
{
private:
    Relay array[N]; //or std::array<Relay, N>
    EWMA_average< D > ewma_average;
public:
    RelayArray(const Relay(&ref)[N]) 
    {}
};

RelayArray myRelayArray{{{2, true}, {4, false}, {6, true}}};

The declaration above "expands" to RelayArray<3, 10> myRelayArray...

Now, I'd like to provide 'D' and only 'D'. 'N' should be again deduced from the declaration. The following works:

RelayArray<3, 5> myRelayArray{{{2, true}, {4, false}, {6, true}}};

but not this uses 5 for the first argument, not for D:

RelayArray<5> myRelayArray{{{2, true}, {4, false}, {6, true}}}; // does not work

What is a way in C++17 or older to make RelayArray<5> choose D=5 and let N be deduced from the initializer?

I've found some solutions with aliases for example, but I'm not satisfied with that.

BTW: I cannot use any STL-containers nor any STL-"stuff"...Not available for avr-gcc :-(

Thx Fred


Solution

  • I finally found a way to do it this way, defining 2 ctors.

    public:
        RelayArray(const Relay(&ref)[N]) : array(ref)
        {}
        RelayArray(integral_constant< uint8_t, D > ic, const Relay(&ref)[N]) : array(ref)
        {}
    

    Now I can instantiate like that :

    RelayEngine relays{ { { 3, 1000, 200, 1, 1 } } };
    

    which expand to RelayEngine<1, 10> or like that :

    RelayEngine relays{ integral_constant< uint8_t, 15 >{}, { { 3, 1000, 200, 1, 1 } } };
    

    which expands to RelayEngine<1, 15>```

    So now, I "only" need something to avoid writing integral_constant< uint8_t, 15 >{}.