c++ 存在类模板成员函数的显式专用化时使用“extern template”时出错

57hvy0tb  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(120)

考虑一个类模板S
[ s.hpp ]

template <typename>
struct S
{
    void f() { /* ... */ }
    void g() { /* ... */ }
};

这个类模板还附带了一个包含S<int>::g()专门化的源文件:
[ s.cpp ]

template <>
void S<int>::g() { /* ... */ }

S多次示例化为S<int>,为了避免S<int>的多次示例化,加快编译速度,我想在头文件s.hpp中引入一个 * 显式示例化声明 *(extern template),在源文件s.cpp中引入一个对应的 * 显式示例化定义 *:
[ s.hpp ] (已修改)

template <typename>
struct S
{
    void f() { /* ... */ }
    void g() { /* ... */ }
};

extern template struct S<int>;

[ s.cpp ] (已修改)

template <>
void S<int>::g() { /* ... */ }

template struct S<int>;

但是,这样做会导致以下编译错误:

<source>:11:14: error: explicit specialization of 'g' after instantiation
void S<int>::g() { /* ... */ }
             ^
<source>:8:23: note: explicit instantiation first required here
extern template class S<int>;
                      ^

我认为发生错误是因为extern template仍然被认为是一个 * 示例化 *,即使它只是一个声明。

如何通过在S的面向客户端的头文件中提供extern template声明,同时在源文件中保留S<int>::g的显式专用化,来实现可能的编译加速?

w6lpcovy

w6lpcovy1#

也在头中声明显式的专门化。

template <typename>
struct S
{
    void f() { /* ... */ }
    void g() { /* ... */ }
};

template <>
void S<int>::g();

extern template struct S<int>;

提炼规则:在实体成为显式示例化(定义或声明)的主体之前,必须出现显式专门化的声明。因为S<int>的显式示例化递归地构成S<int>::g的相同内容,所以需要提前声明专门化。
但我们应该庆幸我们没有着火。

相关问题