Search code examples
c++templatespolicy

Can C++ policy classes be used to specify existence / non-existence of constructors?


Suppose I have:

struct Magic {
  Magic(Foo* foo);
  Magic(Bar* bar);
};

Is there a way to make Magic a template, and define template classes s.t.

typedef Magic<FooPolicy, ...> MagicFoo;
typedef Magic<BarPolicy, ...> MagicBar;
typedef Magic<..., ...> MagicNone;
typedef Magic<FooPolicy, BarPolicy> MagicAll;

s.t. MagicFoo & MagicAll have the Foo* constructor; MagicBar & MagicAll has the Bar* constructor; and MagicNone nas neither the Foo* nor the Bar* constructor?

Basically I want constructors to exist or not exist based on policy classes.


Solution

  • You can write a constructor accepting anything, and then delegate to whatever the policies provide:

    // "Tag" and "No" are used to make the class/function unique 
    // (makes the using declarations work with GCC). 
    template<int Tag>
    struct No { void init(No); };
    
    template<typename P1 = No<0>, typename P2 = No<1>, typename P3 = No<2> >
    struct Magic : P1, P2, P3 {
      template<typename T>
      Magic(T t) {
        init(t);
      }
    
    private:
      using P1::init;
      using P2::init;
      using P3::init;
    };
    

    Now, once you forward the argument, the compiler will figure out the best match among the policies:

    struct IntPolicy { void init(int) { std::cout << "called int!"; } };
    struct FloatPolicy { void init(float) { std::cout << "called float!"; } };
    Magic<IntPolicy, FloatPolicy> m(0), n(0.0f);