让我们考虑以下三个文件。
tclass.h:
#include <iostream>
#include <vector>
template<typename rt>
class tclass
{
public:
void wrapper()
{
//Storage is empty
for(auto it:storage)
{
}
try
{
thrower();
}
catch(...)
{
std::cout << "Catch in wrapper\n";
}
}
private:
void thrower(){}
std::vector<int> storage;
};
spec.cpp:
#include "tclass.h"
//The exact type does not matter here, we just need to call the specialized method.
template<>
void tclass<long double>::thrower()
{
//Again, the exception may have any type.
throw (double)2;
}
main.cpp中:
#include "tclass.h"
#include <iostream>
int main()
{
tclass<long double> foo;
try
{
foo.wrapper();
}
catch(...)
{
std::cerr << "Catch in main\n";
return 4;
}
return 0;
}
我使用Linux x64,gcc 4.7.2,使用以下命令编译文件:
g++ --std=c++11 *.cpp
首先测试:如果我们运行上面的程序,它会说:
terminate called after throwing an instance of 'double'
Aborted
第二次测试:如果我们在for(auto it:storage)
文件中发表评论tclass.h
,程序将在main
函数中捕获异常。 WAT 为什么呢?是否试图迭代空向量导致堆栈损坏?
第三次测试:让我们取消注释for(auto it:storage)
行并将方法专精从spec.cpp
移到main.cpp
。然后在wrapper
中捕获异常。怎么可能,为什么可能的内存损坏不会影响这种情况呢?
我还尝试使用不同的优化级别和-g
编译它,但结果是相同的。
然后我在Windows 7 x64,VS2012 express上尝试了它,使用x64版本的cl.exe进行编译,没有额外的命令行参数。在第一次测试时,这个程序没有输出,所以我认为它只是默默地崩溃,所以结果与Linux版本相似。对于第二次测试,它不再产生输出,因此结果与Linux不同。对于第三次测试,结果与Linux结果类似。
此代码中是否有任何错误,导致此类行为?可能第一次测试的结果是由编译器中的可能错误引起的?
答案 0 :(得分:2)
使用您的代码,我使用gcc 4.7.1:
spec.cpp:6: multiple definition of 'tclass<long double>::thrower()'
您可以通过将.h中的专业化声明为:
来更正您的代码 template<> void tclass<long double>::thrower();