【问题标题】:Error when explicitly converting a template non-type parameter显式转换模板非类型参数时出错
【发布时间】:2015-09-25 18:51:55
【问题描述】:

考虑代码:

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?!
}

我理解注释调用失败的原因:模板类型必须完全匹配。但是,我尝试在第二次调用中进行强制转换,并收到此错误(gcc5.2):

错误:“d”不是“Base&”类型的有效模板参数,因为它不是具有外部链接的对象

如果我将Derived d; 设为全局,则会出现同样的错误。 clang 更有帮助,说

...注意:候选模板被忽略:显式指定无效 模板参数“b”的参数

我的问题是:上面的代码是否合法?如果不是,有什么原因吗?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    此答案假定 C++11 或更高版本

    这里有两个问题:

    1) 非类型模板参数 [temp.arg.nontype]/p1

    没有派生到基础的转换

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

    ——一个子对象(1.8),

    2) 对象的地址应该在编译时可用。总结 [temp.arg.nontype]/p1[expr.const]/p5 它应该有static storage duration

    把这两点放在一起,你就会得到下面的编译

    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>();
    }
    

    Live Example

    【讨论】:

      【解决方案2】:

      来自 [temp.arg.nontype]:

      非类型模板参数模板参数应为转换后的常量表达式(5.20) 模板参数的类型

      这里有两个问题。首先,d 没有链接,因此您不能在常量表达式中引用它。不过,这很容易解决:

      Derived d;
      int main() {
          f<d>(); // still an error
      }
      

      现在,我们还有另一个问题。我们进入下一句:

      对于引用或指针类型的非类型模板参数, 常量表达式的值不应引用(或对于指针类型,不应是地址):
      (1.1) — 一个子对象 (1.8),

      我们正在尝试引用Derived 的子对象(基类子对象)。无论链接如何,这都是明确不允许的。

      【讨论】:

        猜你喜欢
        • 2015-03-26
        • 2016-03-01
        • 2021-09-02
        • 2021-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-06
        相关资源
        最近更新 更多