Reputation: 608
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'
How do I pass a reference to a static instance of type Base
, given the static Derived
object myobject
?
Upvotes: 4
Views: 1646
Reputation: 170065
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