实例化错误后的成员函数模板的专业化,以及成员函数的顺序

时间:2014-01-14 11:14:31

标签: c++ templates template-specialization

以下位代码无法在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<bool>()之前出现了Frobnigator::foo<bool>()的特化,从而解决了这个问题。显然,方法看起来很重要。

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

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

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

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

int main()
{
}

2 个答案:

答案 0 :(得分:25)

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

n3376 14.7.3 / 6

如果模板,成员模板或类模板的成员是明确专用的,则应在首次使用该特化之前声明特化,这将导致隐式实例化 在发生此类使用的每个翻译单位中发生;无需诊断。

在您的情况下 - 在显式特化声明之前,barbool使用foo<bool> {{1}}函数的隐式实例化。

答案 1 :(得分:3)

  

显然,方法看起来很重要。

实际上;就像在C ++中的情况一样,在声明它之前你不能使用它,这适用于显式模板特化以及大多数其他事情。

使用bar<bool>(通过从foo<bool>调用它)而不事先声明显式特化会导致从泛型模板实例化该特化(如果尚未实现)。你至少需要一个明确的专业化声明来防止这种情况。

  

为什么会这样,考虑到bar的专业化出现在上面代码的以下lite版本中的泛型版本之后

第二个例子的不同之处在于根本没有实例化foo<bool>。问题不在于通用模板(必须是这种情况)之后声明专门化,而是在专业化已经实例化之后声明它。