单独对象的单个模板实例化

Single template instantiation for separate objects

本文关键字:实例化 单个模 对象 单独      更新时间:2023-10-16

考虑以下内容:

/* 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,所以我可能不会向它们引入匿名命名空间。有模板侧的解决方案吗?因此是第二个模板参数

你的程序违反了ODR(一个定义规则),包含了struct Local的两个定义。这意味着它是错误的,并且具有未定义行为,所以任何事情都可能发生。

正如已经指出的那样,你违反了一个定义规则。

你可以在匿名命名空间中定义你的局部结构,这样编译器就知道你在谈论不同的局部类型,然后一切都应该"工作":

/* A.cpp */
namespace {
    struct Local {
        int a[2];
    }
}
/* B.cpp */
namespace {
    struct Local {
        int a[4];
    }
}