我观察到这种奇特的现象,即如果g ++仅用于内联,则g ++不会导出模板函数实例。当然,对于常规的非模板化函数,情况并非如此。例如:
// main.cpp
#include <iostream>
#include "inc.h"
int main() {
std::cout << func<3>() << std::endl;
std::cout << func2() << std::endl;
return 0;
}
// inc.h
template<int num>
int func();
int func2();
// a.cpp
template<int num>
int func() {
return num;
}
int func2() {
return 5;
}
int result;
int result2;
void instantiate() {
// store the results in globally visible variables
// so the compiler won't optimize them out completely
result = func<3>();
result2 = func2();
}
如果我使用-O0
对上述内容进行编译,则链接成功 - objdump
确认func2
生成func<3>
和a.o
的二进制代码, instantiate
正在进行两次函数调用,即函数没有内联。
但是,-O3
更改了内容 - instantiate
不包含函数调用,并且程序集中未生成func<3>
,从而导致链接器错误。当然,func2
仍在那里。
我在实际代码中对此感到厌烦,期望导出函数并获取链接器错误。这种行为有望吗?编译器是否可以确信生成函数,即使它们仅在他们实现的编译单元中内联使用?在我的例子中,我们有许多模板专业化。显式实例化是不切实际的。