考虑一下代码:
class Base{};
class Derived: public Base{};
template<Base& b> // references (and pointers) can be used as non-types
void f(){}
int main()
{
Derived d;
// f(d); // Error, template type must match exactly
f<(Base&)d>(); // Error here, why?!
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么注释调用失败:模板类型必须完全匹配.我在第二次调用中尝试使用强制转换,并得到此错误(gcc5.2):
错误:'d'不是类型'Base&'的有效模板参数,因为它不是具有外部链接的对象
如果我做Derived d;全局,同样的错误.clang更有帮助,说
...注意:候选模板被忽略:模板参数'b'的显式指定参数无效
我的问题是:上面的代码是否合法?如果没有,有什么理由吗?
此答案假定 C++11 或更高版本
这里有两个问题:
1) 非类型模板参数[temp.arg.nontype]/p1没有派生到基类的转换
对于引用或指针类型的非类型模板参数,常量表达式的值不得引用(或对于指针类型,不得为以下地址):
— 一个子对象 (1.8),
2) 对象的地址在编译时应该是可用的。总结[temp.arg.nontype]/p1和[expr.const]/p5,它应该有静态存储持续时间。
将这两点放在一起,您将得到以下编译
class Base{};
class Derived: public Base{};
template<Base& b> // references (and pointers) can be used as non-types
void f(){}
Base obj; // Static storage duration
int main()
{
f<obj>();
}
Run Code Online (Sandbox Code Playgroud)