【问题标题】:Explicit specialization after instantiation实例化后的显式特化
【发布时间】:2011-12-08 02:52:47
【问题描述】:

我有以下代码:

typedef vector<int> Vec;
typedef vector<Vec> VecOfVec;

template<typename Vec>
Vec DoSomething(const Vec &v);

template<>
VecOfVec DoSomething<VecOfVec>(const VecOfVec &v)
{
    VecOfVec r;
    for(auto i = v.begin(); i != v.end(); i++)
        r.push_back(DoSomething(*i));
    return r;
}

template<>
Vec DoSomething<Vec>(const Vec &v) // Error here
{
    return v; // for the sake of the example
}

我收到以下错误:

explicit specialization of 'DoSomething<vector<int> >' after instantiation

在标记线处。
编译器坚持认为它已经实例化了DoSomething&lt;vector&lt;int&gt; &gt;,但它不能,一个简单的程序可以证明这一点:

typedef vector<int> Vec;
typedef vector<Vec> VecOfVec;

template<typename Vec>
Vec DoSomething(const Vec &v);

template<>
VecOfVec DoSomething<VecOfVec>(const VecOfVec &v)
{
    VecOfVec r;
    for(auto i = v.begin(); i != v.end(); i++)
        r.push_back(DoSomething(*i));
    return r;
}

导致无法解决的外部问题。
为什么编译器说它已经实例化了它,而它不能甚至没有?为什么编译器不将其视为未解析的符号,而链接器却将其视为未解析的符号? 我知道切换方法顺序可以解决它,但我想知道编译器为什么要这样做。

【问题讨论】:

    标签: c++ templates template-specialization


    【解决方案1】:

    代码在DoSomething(*i) 请求了一个隐式实例化。您没有在该翻译单元中定义模板这一事实意味着它无法实例化专业化,因此 DoSomething(*i) 在您的情况下会产生“未解析的符号”(链接器)错误。要消除该错误,您要么必须在该 TU 中定义模板,要么在定义模板的 TU 中提供该模板的显式实例化指令。

    在您明确提供专门化足以使程序不正确之前,代码请求了专门化 DoSomething&lt;vector&lt;int&gt; &gt; 的隐式实例化这一事实(尽管不需要诊断;编译器在这方面做得很好)不需要这样做)。

    正如@CharlesBailey 有用地指出的那样,声明明确的专业化就足够了;它的定义可以在其他地方给出,甚至在使用 TU 之外。

    【讨论】:

    • “无需诊断”:标准中是否需要诊断?
    • 我认为部分 “在您明确提供专业化足以使程序变得不正确之前,代码要求隐式实例化专门化 DoSomething&lt;vector&lt;int&gt; &gt; 的事实” i> 不正确,或者其中缺少某些内容。它应该是:在您明确提供专业化足以使程序生病之前,代码要求从 完全专业化 为专业化 DoSomething&lt;vector&lt;int&gt; &gt; 进行隐式实例化这一事实 -形成。如果我错了纠正我。 :-)
    • @Nawaz:所以你们都说隐式与显式不同,它们不能互换?
    • 您只需在会导致隐式实例化的代码之前声明显式特化。该定义可以在其他地方提供。
    • @Nawaz 我写的内容会导致隐式实例化。即使在提供显式特化之前从函数模板中引发隐式实例化,也会得到格式错误 (NDR) 的程序:template&lt;typename T&gt; void f() { DoSomething&lt;vector&lt;int&gt; &gt;(vector&lt;int&gt;()); }
    【解决方案2】:

    通常这只是意味着您没有为模板专业化提供“原型”。换句话说,您没有提醒编译器“嘿,这种特定类型的函数将会有专门化,所以不要插入错误的。”

    在我的例子中,我在 .cpp 文件中有一个模板特化,并得到了这个错误。提供一个“函数原型”(它只是模板特化标头后跟一个分号,就像常规函数原型一样)解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-25
      • 1970-01-01
      • 2019-04-15
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      • 1970-01-01
      相关资源
      最近更新 更多