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

Specialization of member function template after instantiation error, and order of member functions

本文关键字:成员 函数 顺序 专业化 错误 函数模板 实例化      更新时间:2023-10-16

以下代码在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::foo<bool>()之前出现Frobnigator::bar<bool>()的专业化来解决这个问题。显然,这些方法出现的顺序很重要。

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

struct Frobnigator
{
template<typename T>
void foo();
};
template<typename T>
void Frobnigator::bar()
{
}
template<>
void Frobnigator::bar<bool>()
{
}
int main()
{
}

您的第一个代码不符合标准。

n3376 14.7.3/6

如果模板、成员模板或类模板的成员是显式专用化的,则应在首次使用该专用化之前声明该专用化,这将导致隐式实例化在发生此类使用的每个翻译单元中发生;不需要进行诊断

在您的案例中,bool类型的bar函数的隐式实例化是foo<bool>中使用它所必需的,在显式专用化声明之前。

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

确实;就像C++中通常的情况一样,在声明之前不能使用某个东西,这适用于显式模板专业化以及大多数其他事情。

使用bar<bool>(通过从foo<bool>调用它)而不事先声明显式专业化会导致该专业化从通用模板实例化,如果它还没有实例化的话。你们至少需要一份明确的专业化声明来防止这种情况的发生。

为什么会出现这种情况,考虑到bar的专业化出现在上述代码的以下精简版本中的通用版本之后

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