1

I'm abstracting the interrupt vector table on multiple microcontrollers. I am using template classes in the form of (InterruptVectorTable.hpp(definition, included in implementation))

template<class Device, class ResultType>
InterruptVectorTable
{
    enum class IRQType : ResultType;

}

Device is a kind of dummy class that is used to specialize the template.

class DeviceAtMega328p 
{
      public:
        static const int s_NumInterruptVectors = {26};
};

(Here I'm still thinking about whether to pass the 26 as template parameter or in this form.)

As each microcontroller has its own types and values of interrupts, that should be checked at compile time (because of enum class), I'd like to also specialize the specific interrupts in this form(InterruptVectorTable.hpp(Implementation):

template<>
InterruptVectorTable< DeviceAtMega328p, uint8_t>
{
    enum class IRQType : ResultType
    {
        //RESET_IRQn = 0,               // Not available.
        INT0_IRQn = 1,
        INT1_IRQn = 2,
        PCINT0_IRQn = 3,
        PCINT1_IRQn = 4,
        PCINT2_IRQn = 5,
        WDT_IRQn = 6, 
        // .....
    };
}

This approach seems not to work as expected(currently too many errors to specify, which explicitly one specifies this part).

John Behm
  • 101
  • 1
  • 5
  • Please provide a [mre], your code as posted doesn't compile due to lack of the original `InterruptVectorTable` class. You're probably in need of some sort of traits pattern but its difficult to say without more details – Alan Birtles Jan 09 '20 at 17:26
  • The Atmega328p (usually found in Arduino UNOs) does not support the C++ standard library, thus only "basic" C++ facilities apply. – John Behm Jan 09 '20 at 17:40
  • 2
    You don't need the standard library to implement a traits pattern, its a language feature – Alan Birtles Jan 09 '20 at 18:21

1 Answers1

3

First of all, this is not how you introduce a new template class:

// Wrong!
template<>
InterruptVectorTable<class Device, class ResultType>
{
    // ...
}

Right way:

template<class Device, class ResultType>
class InterruptVectorTable
{
    // ...
};

Second, you can't "forward-declare" something in a template that the template specializations will have to define. The specialization knows nothing about and has nothing in common with the "base case".

Your code will work if you just do:

template<>
class InterruptVectorTable<DeviceAtMega328p, uint8_t>
{
    enum class IRQType : uint8_t
    {
        //RESET_IRQn = 0,               // Not available.
        INT0_IRQn = 1,
        INT1_IRQn = 2,
        PCINT0_IRQn = 3,
        PCINT1_IRQn = 4,
        PCINT2_IRQn = 5,
        WDT_IRQn = 6, 
        //...........
    };
};

Users of InterruptVectorTable will simply assume that each specialization defines an enum class IRQType. There is no direct way to force specializations to do so. Same story for the requirement of IRQType having ResultType as underlying type.

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
  • Well, my problem extends to the `InterruptVectorTable` base class defining member functions that depend on arguments of type `IRQType` being passed. ```auto setCallback(IRQType InterruptIndex, void (*Callback)(void)) -> void;```, might maybe pass the IRQType as template parameter? – John Behm Jan 09 '20 at 19:05
  • @JohnBehm Passing `IRQType` as template parameter could be an option, but it will have to be defined before (as in outside) the specialization for that to work. – Max Langhof Jan 10 '20 at 08:40