Почему это работает?
Я вижу похожие вопросы о том, что это так, но может кто-нибудь объяснить это более подробно? В частности, защищено ли это поведение стандартом?
i.h
#ifndef I_H_
#define I_H_
typedef void (*FuncPtr)();
template<typename T>
void FuncTemplate() {}
class C {};
#endif
a.cc
#include "i.h"
FuncPtr a() {
return &FuncTemplate<C>;
}
b.cc
#include "i.h"
FuncPtr b() {
return &FuncTemplate<C>;
}
m.cc
#include <iostream>
#include "i.h"
FuncPtr a();
FuncPtr b();
int main() {
std::cout << (a() == b() ? "equal" : "not equal") << std::endl;
return 0;
}
Тогда
$ g++ -c -o a.o a.cc
$ g++ -c -o b.o b.cc
$ g++ -c -o m.o m.cc
$ g++ a.o b.o m.o -o prog
$ ./prog
equal
Вбрасывание -Wall -Wextra -Werror -ansi
на все вызовы g++
производит то же самое.
Мое (наивное) понимание состоит в том, что FuncTemplate
создается один раз в каждом из блоков компиляции a.o
и b.o
, и поэтому каждый адрес должен указывать на одну копию. Как они в конце концов остаются одинаковыми, и это поведение переносимо или защищено?
РЕДАКТИРОВАТЬ Корпус общей библиотеки:
$ g++ -shared -o liba.so a.cc
$ g++ -shared -o libb.so b.cc
$ g++ -c -o m.o m.cc
$ g++ -L. -la -lb m.o -o prog
$ ./prog
equal