显式转换模板非类型参数时出错

vso*_*tco 5 c++ templates

考虑一下代码:

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'的显式指定参数无效

我的问题是:上面的代码是否合法?如果没有,有什么理由吗?

Mar*_* A. 5

此答案假定 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)

Live Example