AndresR
AndresR

Reputation: 608

Pass a reference to a base class as template parameter

I have the following code where I try to specialize a function template for each instance of a class (that may have been derived):

class Base {
};

class Derived:public Base {
};

template<Base& b>
void myfunction() {
   //use b somehow
}

Derived myobject;

int main() {
  myfunction<myobject>(); //this does not work
}

The code results in error message:

candidate template ignored: invalid explicitly-specified argument for template parameter 'b'

[live demo]

How do I pass a reference to a static instance of type Base, given the static Derived object myobject?

Upvotes: 4

Views: 1646

Answers (1)

While it is fine to declare a template non-type parameter as a reference according to [temp.param]/4:

A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

  • ...
  • lvalue reference to object or lvalue reference to function,
  • ...

The argument must follow the restrictions in [temp.arg.nontype]/2:

A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • a subobject,
  • ...

Which explicitly forbids what you are trying to do. Since b is going to end up referring to a sub-object.

The only solution which will make this compile, is adding another overload:

template<Derived & d>
void myfunction()
{
   //use d somehow
}

So you'll need to extract the common code out somehow.

Or, if you have C++17 available:

template<auto& b, std::enable_if_t<
                    std::is_base_of_v<Base, std::decay_t<decltype(b)>>
                  , void*> = nullptr>
void myfunction()
{
   //use b somehow
}

I suggest you re-think your general approach, however.

Upvotes: 5

Related Questions