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

Olu*_*ide 17 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()
{
}
Run Code Online (Sandbox Code Playgroud)

错误讯息:specialization of ‘void Frobnigator::bar() [with T = bool]’ after instantiation.我终于解决了这个问题,因为Frobnigator::bar<bool>()之前出现了专门化Frobnigator::foo<bool>().显然,方法看起来很重要.

那么为什么以上是上面代码的lite版本,其中bar泛型版本之后出现的特化,有效吗?

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

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

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

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

For*_*veR 28

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

n3376 14.7.3/6

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

在您的情况下 - 在显式特化声明之前,它的用法需要隐式实例化bar具有类型的函数.boolfoo<bool>


Mik*_*our 5

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

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

在没有先前声明显式专业化的情况下使用bar<bool>(通过从 调用它foo<bool>)会导致从通用模板实例化该专业化(如果尚未实例化)。您至少需要一个显式专业化声明来防止这种情况发生。

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

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

  • 我认为这是愚蠢的,应该得到解决。它违背了先声明、后定义的计划。Cpp 隐含地做了太多事情。它应该看到我的函数调用,并链接适当的编译函数。请注意,显式声明并不能解决问题。 (2认同)