请考虑以下事项:
/* T.h */
template <class T>
void Too() {
std::cout << " Template: " << typeid(T).name()
<< " size: " << sizeof(T) << std::endl;
}
/* A.h */
extern void FooA();
/* A.cpp */
struct Local {
int a[2];
}
void FooA() {
Local l;
std::cout << "<Foo A>:\n" << " Real: " << typeid(l).name()
<< " size: " << sizeof(l) << std::endl;
Too<Local>();
}
/* B.h */
extern void FooB();
/* B.cpp */
struct Local {
int a[4];
};
void FooB() {
Local l;
std::cout << "<Foo B>:\n" << " Real: " << typeid(l).name() \
<< " size: " << sizeof(l) << std::endl;
Too<Local>();
}
/* main.cpp */
int main() {
FooA();
FooB();
return 0;
}
编译并运行结果:
<Foo A>:
Real: 5Local size: 8
Template: 5Local size: 8
<Foo B>:
Real: 5Local size: 16
Template: 5Local size: 8
这意味着单个模板实例化用于两个模板调用。值得注意的是 - 第一个。
虽然可以通过将Too()
定义为
template <class T, size_t s = sizeof(T)> Too();
我想知道这个问题还有更通用的方法吗?如果两个调用结构的大小相同,上面的代码仍会失败。
修改
具体来说,我的问题在于,我无法更改文件A和B.所以我可能不会向他们引入匿名命名空间。 有没有模板方面的解决方案?因此第二个模板参数。
答案 0 :(得分:7)
您的程序包含两个struct Local
定义,违反了ODR(一个定义规则)。这意味着它形成不良并且具有未定义的行为,因此任何事情都可能发生。
答案 1 :(得分:6)
正如已经指出的那样,你违反了一个定义规则。
您可以在匿名命名空间中定义本地结构,以便编译器知道您正在讨论不同的本地类型,然后一切都应该“正常”:
/* A.cpp */
namespace {
struct Local {
int a[2];
}
}
/* B.cpp */
namespace {
struct Local {
int a[4];
}
}