Tenho um registro singleton que mapeia nomes para ponteiros de função. Também tenho um objeto registrador cujo construtor registra um ponteiro de função.
Meu objetivo é ter as funções e o registro em uma biblioteca estática, mas descobri que o vinculador omite os registros quando construído dessa forma.
Aqui está uma ilustração simplificada. Para resumir, substituí os ponteiros de função por ponteiros para inteiros globais e o contêiner associativo do registro por um vetor.
// registry.h
#include <vector>
std::vector<int const *> &GetRegistry();
// registry.cpp
#include "registry.h"
std::vector<int const *> &GetRegistry() {
static std::vector<int const *> registry;
return registry;
}
// thingadder.h
#include "registry.h"
class ThingAdder {
public:
explicit ThingAdder(int const *thing) {
GetRegistry().push_back(thing);
}
};
// things.cpp
#include "thingadder.h"
int g_thing1 = 1;
ThingAdder g_adder1(&g_thing1);
// main.cpp
#include "registry.h"
#include <print>
#include <vector>
int main() {
std::print("registry size: {}\n", GetRegistry().size());
return 0;
}
Se todos os arquivos forem compilados e vinculados como um único projeto, g_adder1
o construtor de adiciona g_global1
o endereço de ao registro, e o programa informa que o tamanho do registro é 1.
Mas quando tudo, exceto main.cpp, é criado em uma biblioteca estática, e então main.cpp é compilado e vinculado a essa biblioteca, o tamanho do registro relatado é 0. Parece que os globais em things.cpp foram omitidos pelo link.
Eu meio que entendo por que isso está acontecendo: nada fora de things.cpp faz referência direta ao objeto global nem ao seu registrador. Mas isso é verdade mesmo quando construído como um monolito. Eu não esperaria que incluir essa parte em uma biblioteca estática mudasse o comportamento.
Soluções?
A única solução que encontrei foi fazer com que main.cpp faça referência a um símbolo definido na unidade de tradução things.cpp. Na biblioteca em si, haverá mais arquivos de objetos a serem registrados, e não quero que cada usuário da biblioteca adicione uma referência a um símbolo para cada um deles.