Je souhaite créer une alternative à l' std::type_index
qui ne nécessite pas de RTTI:
template <typename T>
int* type_id() {
static int x;
return &x;
}
Notez que l'adresse de la variable locale x
est utilisée comme type ID, et non de la valeur de x
lui-même. Aussi, je n'ai pas l'intention d'utiliser un pointeur nu dans la réalité. J'ai juste enlevé tout n'est pas pertinente à ma question. Voir mon effectif type_index
mise en œuvre ici.
Est-ce l'approche de son, et si oui, pourquoi? Si non, pourquoi pas? J'ai l'impression que je suis sur des bases fragiles, ici, donc je suis intéressé par les raisons précises pour lesquelles mon approche sera ou ne sera pas de travail.
Un cas d'utilisation typique pourrait être d'enregistrer des routines au moment de l'exécution de manipuler des objets de types différents à travers une interface unique:
class processor {
public:
template <typename T, typename Handler>
void register_handler(Handler handler) {
handlers[type_id<T>()] = [handler](void const* v) {
handler(*static_cast<T const*>(v));
};
}
template <typename T>
void process(T const& t) {
auto it = handlers.find(type_id<T>());
if (it != handlers.end()) {
it->second(&t);
} else {
throw std::runtime_error("handler not registered");
}
}
private:
std::map<int*, std::function<void (void const*)>> handlers;
};
Cette classe peut être utilisée comme suit:
processor p;
p.register_handler<int>([](int const& i) {
std::cout << "int: " << i << "\n";
});
p.register_handler<float>([](float const& f) {
std::cout << "float: " << f << "\n";
});
try {
p.process(42);
p.process(3.14f);
p.process(true);
} catch (std::runtime_error& ex) {
std::cout << "error: " << ex.what() << "\n";
}
Conclusion
Merci à tous pour votre aide. J'ai accepté la réponse de @Conteur, comme il l'a expliqué pourquoi la solution doit être valide selon les règles de C++. Toutefois, @SergeBallesta et un certain nombre d'autres dans les commentaires ont souligné que MSVC effectue des optimisations qui viennent trop près de la rupture de cette approche. Si une approche plus rigoureuse est nécessaire, puis une solution à l'aide d' std::atomic
peut être préférable, comme suggéré par @galinette:
std::atomic_size_t type_id_counter = 0;
template <typename T>
std::size_t type_id() {
static std::size_t const x = type_id_counter++;
return x;
}
Si quelqu'un a des pensées ou des renseignements, je suis toujours avide de l'entendre!