【问题标题】:Specialization of member function template after instantiation error, and order of member functions实例化错误后成员函数模板的特化,以及成员函数的顺序
【发布时间】:2014-02-02 10:19:23
【问题描述】:

以下代码在 gcc 4.5.3 上编译失败

struct Frobnigator
{
    template<typename T>
    void foo();

    template<typename T>
    void bar(); 
};

template<typename T>
void Frobnigator::bar()
{
}

template<typename T>
void Frobnigator::foo()
{
    bar<T>();
}

template<>      // error
void Frobnigator::foo<bool>()
{
    bar<bool>();
}

template<>
void Frobnigator::bar<bool>()
{
}

int main()
{
}

错误消息:specialization of ‘void Frobnigator::bar() [with T = bool]’ after instantiation。我终于通过将Frobnigator::bar&lt;bool&gt;() 的特化出现在Frobnigator::foo&lt;bool&gt;() 之前解决了这个问题。显然,方法出现的顺序很重要。

那么为什么上面代码的以下精简版,其中bar的特化出现在通用版本之后,有效?

struct Frobnigator
{
    template<typename T>
    void foo();
};

template<typename T>
void Frobnigator::bar()
{
}

template<>
void Frobnigator::bar<bool>()
{
}

int main()
{
}

【问题讨论】:

    标签: c++ templates template-specialization


    【解决方案1】:

    您的第一个代码按标准不正确。

    n3376 14.7.3/6

    如果模板、成员模板或类模板的成员是显式特化的,则应在第一次使用会导致隐式实例化的特化之前声明该特化 在发生这种使用的每个翻译单元中发生;不需要诊断。

    在您的情况下 - 在显式特化声明之前,bar 类型为 bool 的函数的隐式实例化需要在 foo&lt;bool&gt; 中使用。

    【讨论】:

      【解决方案2】:

      显然,方法出现的顺序很重要。

      确实;与 C++ 中的常见情况一样,您不能在声明之前使用某些东西,这适用于显式模板特化以及大多数其他东西。

      使用bar&lt;bool&gt;(通过从foo&lt;bool&gt; 调用它)而不事先声明显式特化会导致从通用模板实例化该特化(如果尚未实例化)。您至少需要一个显式特化声明来防止这种情况发生。

      为什么会这样,考虑到上面代码的以下精简版中,bar的特化出现在通用版本之后

      第二个示例的不同之处在于根本不实例化foo&lt;bool&gt;。问题不在于特化是在泛型模板之后声明的(必须如此),而是它是在该特化已经实例化之后声明的。

      【讨论】:

      • 我认为这很愚蠢,应该解决。它破坏了先声明后定义的计划。 Cpp 隐含地做了太多的事情。它应该看到我的函数调用,并链接适当的编译函数。请注意,显式声明不能解决问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 2012-05-09
      相关资源
      最近更新 更多