Search code examples
c++c++11templatesstatic-assert

Use static_assert to ensure template parameter is only used *at most* once


Is it possible to ensure a certain template parameter (or combination of template parameters) is used - at most - once? Would it be possible to track the number of times it's used, and throw a static_assert error if it was used more than once?

As an example - let's say I wanted to create a static, template-based GPIO class:

template<uint8_t Port, uint8_t Pin> class Gpio {};

One could feasibly lay out their entire board in a single Board class:

struct Board {
  Gpio<1, 1> myInputPin;
  Gpio<1, 2> myOutputPin;

  Gpio<2, 0> ledR;
  Gpio<2, 1> ledG;
  Gpio<2, 2> ledB;
};

For any given port/pin combination, it only makes sense for a single GPIO template to be instantiated for that port and pin. If someone creates two different GPIO instances for the same port/pin combination, it likely represents a conflict, and I would like to catch this error during compilation.

Is this possible?


Solution

  • You can solve this problem with a macro:

    #define GPIO(Port, Pin) \
        friend void _gpio_ ## Port ## _ ## Pin(){} \
        Gpio<Port, Pin>
    

    Then if you use GPIO(2, 2) twice, the compiler will say something like this:

    error: redefinition of '_gpio_2_2'
      GPIO(2, 2) ledX;
      ^
    
    <source>:14:3: note: previous definition is here
      GPIO(2, 2) ledB;
      ^
    

    Demo: https://godbolt.org/z/ronV0u