将基类的引用作为模板参数传递

And*_*esR 4 c++ templates

我有以下代码,我尝试为类的每个实例(可能已派生)专门化一个函数模板:

class Base {
};

class Derived:public Base {
};

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

Derived myobject;

int main() {
  myfunction<myobject>(); //this does not work
}
Run Code Online (Sandbox Code Playgroud)

该代码会产生错误消息:

candidate template ignored: invalid explicitly-specified argument for template parameter 'b'
Run Code Online (Sandbox Code Playgroud)

[现场演示]

给定静态对象Base,如何传递对类型的静态实例的引用?Derivedmyobject

Sto*_*ica 5

虽然根据[temp.param]/4声明模板非类型参数作为引用可以的:

非类型模板参数应具有以下类型之一(可选 cv 限定):

  • ...
  • 对对象的左值引用或对函数的左值引用,
  • ...

参数必须遵循[temp.arg.nontype]/2中限制:

非类型模板参数的模板参数应是模板参数类型的转换后的常量表达式。 对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或对于指针类型,不应是以下地址):

  • 一个子对象
  • ...

这明确禁止您尝试做的事情。因为b最终将引用一个子对象。

使这个编译的唯一解决方案是添加另一个重载:

template<Derived & d>
void myfunction()
{
   //use d somehow
}
Run Code Online (Sandbox Code Playgroud)

因此,您需要以某种方式提取通用代码。

或者,如果您有可用的 C++17:

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
}
Run Code Online (Sandbox Code Playgroud)

不过,我建议您重新考虑您的总体方法。