我希望有人能指出在使用“外部模板类”和“模板类”使用gnu c++进行显式实例化时,在模板类中专门化方法的正确方法。我试着用一个最简单的例子来总结这个问题,这个例子模拟了我真正的问题。声明“外部模板”似乎意味着模板实例化,这会在专门化方法时导致错误。给定一个驱动程序:
main.cc
#include A_H
#include <iostream>
int main()
{
A<int> ai;
A<long> al;
std::cout << "ai=" << ai.get() << " al=" << al.get() << std::endl;
return 0;
}和下面的A的实现
a.h
template<typename T>
struct A
{
int get() const;
};
extern template class A<int>;
extern template class A<long>;a.cc
#include "a.h"
template<typename T>
int A<T>::get() const
{
return 0;
}
template<>
int A<long>::get() const
{
return 1;
}
template class A<int>;
template class A<long>;当使用g++ 4.1.2或4.4.4进行编译时,我收到以下错误
% g++ -Wall -g -D'A_H="a.h"' a.cc main.cc
a.cc:10: error: specialization of 'int A<T>::get() const [with T = long int]' after instantiation
%如果我注释掉a.h中的两个"extern template“行,那么两个编译器都会按照预期进行编译和工作。我假设在没有“外部模板”的情况下依赖于显式实例化的存在即使在C++0x中也是未指定的行为,否则,C++0x添加“外部模板”有什么意义呢?
如果我将A实现为:
a-hack.h
template<typename T>
struct A
{
int get() const;
};
template<typename T>
int A<T>::get() const
{
return 0;
}
template<>
inline
int A<long>::get() const
{
return 1;
}
extern template class A<int>;
extern template class A<long>;a-hack.cc
#include "a-hack.h"
template class A<int>;
template class A<long>;并再次编译,这将按预期工作
% g++ -Wall -g -D'A_H="a-hack.h"' a-hack.cc main.cc
% ./a.out
ai=0 al=1然而,在我的真实示例中,这会导致使用g++ 4.1.2 (在使用g++ 4.4.4时)的程序崩溃。我还没有缩小崩溃的确切原因(分段故障)。它只是看起来好像堆栈指针在调用A<>::get()时已损坏。
我意识到显式模板实例化在这一点上是非标准的,但是有人会期望我上面所做的工作能起作用吗?如果不是,正确的方法是什么?
谢谢
发布于 2011-03-19 02:34:01
extern template class A<long>;这一行说明A<long>将根据编译器已经看到的定义进行显式实例化。当您稍后添加专门化时,您就打破了这一含义。
将专门化的声明添加到头文件中。
template <typename T> struct A { /*...*/ };
template<> int A<long>::get() const;
extern template class A<int>;
extern template class A<long>;一般而言,最好将尽可能多的专门化声明放在与主模板相同的头文件中,以减少编译器关于应将哪个声明用于任何特定实例化的意外。
请注意,如果您正在处理单个模板实体,则extern template声明不是必需的(与本例相反,在本例中,我们必须指示编译器有关类A<long>和函数A<long>::get())。如果你想在另一个翻译单元中专门化一个函数模板,只需编写template<>就足够了。
template<typename T> int freeGet() { return 0; } // you can even add "inline" here safely!
template<> int freeGet<long>(); // this function is not inline (14.7.3/12)但是你必须在那里有<>。如果省略了<>,声明将变成默认实现(return 0)的显式实例化,这可能不是您想要的!即使添加了extern,编译器也可以内联该默认实现;如果在传递-O2时代码意外中断,则可能意外地在某处遗漏了<>。
发布于 2015-12-24 16:13:08
添加此答案以解决标题中的问题(模板实例化,而不一定是模板方法实例化)。
这非常类似于函数声明/定义。
header.
extern template class是一个声明,通常应该放在header.
是一个定义,一般应该放在cpp中。declaration.
更多信息here。
https://stackoverflow.com/questions/5356269
复制相似问题