以下位代码无法在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()
{
}
答案 0 :(得分:25)
您的第一个代码标准不正确。
n3376 14.7.3 / 6
如果模板,成员模板或类模板的成员是明确专用的,则应在首次使用该特化之前声明特化,这将导致隐式实例化 在发生此类使用的每个翻译单位中发生;无需诊断。
在您的情况下 - 在显式特化声明之前,bar
中bool
使用foo<bool>
{{1}}函数的隐式实例化。
答案 1 :(得分:3)
显然,方法看起来很重要。
实际上;就像在C ++中的情况一样,在声明它之前你不能使用它,这适用于显式模板特化以及大多数其他事情。
使用bar<bool>
(通过从foo<bool>
调用它)而不事先声明显式特化会导致从泛型模板实例化该特化(如果尚未实现)。你至少需要一个明确的专业化声明来防止这种情况。
为什么会这样,考虑到bar的专业化出现在上面代码的以下lite版本中的泛型版本之后
第二个例子的不同之处在于根本没有实例化foo<bool>
。问题不在于通用模板(必须是这种情况)之后声明专门化,而是在专业化已经实例化之后声明它。