Почему это работает?
Я вижу похожие SO-вопросы, в которых говорится, что это так, но не мог бы кто-нибудь объяснить это более подробно? В частности, защищено ли это поведение стандартом?
ih
#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
Tossing -Wall -Wextra -Werror - ansi
для всех вызовов g ++
дает то же самое.
Мое (наивное) понимание состоит в том, что FuncTemplate
создается один раз в каждом из модулей компиляции ao
и bo
, поэтому каждый адрес должен указывать на один экземпляр. Как они в конечном итоге останутся такими же, и будет ли это поведение переносимым или защищенным?
РЕДАКТИРОВАТЬ Случай с общей библиотекой:
$ 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