2

I would like to have a class, let's say a queue, that can be specialized to its behavior. For example, let them be a SafeQueue (which disables IRQs before any access) and a FastQueue (which doesn't). As you see, the vast majority of the common code would be just the queue itself.

Please tell me what you think about the below implementation. Is it something you would expect to see in the codebase? Is there a better/standard solution?

struct IrqGuard { IrqGuard(){fmt::print("Disable IRQ\n");} ~IrqGuard(){fmt::print("Enable IRQ\n");} }; struct NoGuard { }; template<typename T, typename GuardT> struct BaseQueue { bool push(T val) { [[maybe_unused]] GuardT guard; fmt::print("Pushing {}\n", val); return true; } }; template<typename T> struct SafeQueue : public BaseQueue<T, IrqGuard>{}; template<typename T> struct FastQueue : public BaseQueue<T, NoGuard>{}; 

Example usage: https://godbolt.org/z/rjnYr4Weq

1 Answer 1

7

It's absolutely fine and perfectly normal.

Modifying behaviour with a template parameter like this is usually called a Policy to distinguish it from the Strategy pattern, which is exactly the same thing with run-time instead of compile-time polymorphism (see Modern C++ Design and the GoF Design Patterns book).

My only criticisms are

  1. that the template alias style has been idiomatic since C++11, and is slightly less typing:

    template<typename T> using SafeQueue = BaseQueue<T, IrqGuard>; 
  2. that if you ever need to write higher-level metafunctions over a BaseQueue, it's a little easier if you re-export your template parameters, like:

    template<typename T, typename GuardT> struct BaseQueue { using value_type = T; using guard_type = GuardT; 
1
  • 5
    Perfectly normal, as in std::basic_string<char, std::char_traits<char>>, a.k.a. std::string Commented Oct 31, 2022 at 15:31

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.