Я хочу создать альтернативу std::type_index
, которая не требует RTTI:
template <typename T>
int* type_id() {
static int x;
return &x;
}
Обратите внимание, что адрес локальной переменной x
используется как идентификатор типа, а не значение x
. Кроме того, я не намерен использовать голый указатель в реальности. Я просто убрал все, что не касается моего вопроса. См. Текущую реализацию type_index
здесь.
Этот подход звучит, и если да, то почему? Если нет, почему бы и нет? Я чувствую, что я нахожусь на шаткой почве здесь, поэтому меня интересуют точные причины, по которым мой подход будет или не будет работать.
Типичным примером использования может быть регистрация подпрограмм во время выполнения для обработки объектов разных типов через один интерфейс:
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;
};
Этот класс может быть использован следующим образом:
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";
}
Заключение
Спасибо всем за вашу помощь. Я принял ответ от @StoryTeller, поскольку он изложил, почему решение должно быть действительным в соответствии с правилами С++. Тем не менее, @SergeBallesta и ряд других в комментариях указали, что MSVC выполняет оптимизацию, которая неудобно близка к нарушению этого подхода. Если требуется более надежный подход, то предпочтительным может быть решение с использованием std::atomic
, как это было предложено в @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;
}
Если у кого-то есть другие мысли или информация, я все еще хочу его услышать!