【发布时间】:2011-03-18 18:25:10
【问题描述】:
我希望有人可以指出在使用“extern 模板类”和“模板类”进行 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的实现
啊。
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 中的两个“外部模板”行,两个编译器都会按预期编译和工作。我假设在没有“外部模板”的情况下存在显式实例化是未指定的行为,即使在 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() 的调用中被破坏了。
我意识到在这一点上显式模板实例化是非标准的,但有人会期望我在上面所做的工作吗?如果不是,那么正确的做法是什么?
谢谢
【问题讨论】:
-
c++0x 去掉了extern模板,因为太难实现了吧?
-
@VJo:
export已删除。extern(用于模板)已添加。 -
@James 一定是新的东西,因为到目前为止我还没有看到导出的模板
-
@VJo:是的,它是 C++0x 中的新功能,尽管一些编译器已经支持它作为扩展已有一段时间了。自 2005 年以来,Visual C++ 就拥有它。