С++ Получить std::typeindex типа, в настоящее время помогающего std::variant

Как я могу получить std::typeindex типа, который в настоящее время помогает, с помощью варианта на С++?

Скажем, у меня есть вариант:

using variant_t = std::variant<int, float, bool, double, std::string>;

Я хочу иметь возможность создать функцию:

std::typeindex get_held_type(const variant_t& var);

Это просто из любопытства, я знаю, что это не обычный способ обработки данных в варианте.

Если я добавлю еще один тип к variant_t, я не хочу менять какой-либо другой код. т. е. типы должны быть саморегистрируемыми.

Вот моя попытка до сих пор. Я немного обманываю, так как использую карту вместо функции, и объект должен быть создан для регистрации типов во время выполнения.

#include <iostream>
#include <variant>
#include <string>
#include <vector>
#include <typeindex>
#include <map>

using variant_t = std::variant<int, float, bool, double, std::string>;
static constexpr size_t variant_t_size = std::variant_size<variant_t>();
static auto get_held_type = std::map<size_t, std::type_index>{};

//loop across all types in the variant
template<size_t N>
struct crtp : crtp<N - 1>{
    //ctor
    crtp(){
        get_held_type[N] = std::type_index(typeid (std::get<N>(variant_t{})));
    }
};

template<>
struct crtp<0>{
    //ctor
    crtp(){
        get_held_type[0] = std::type_index(typeid (std::get<0>(variant_t{})));
    }
};

static crtp<variant_t_size-1> registerTypes;

int main()
{
    variant_t var = 3.141;
    std::cout << get_held_type[var.index()].name() << std::endl;

}

Но это не удается с gcc с ошибкой компилятора:

/usr/include/c++/9/tuple:1674: error: no matching function for call to ‘std::type_index::type_index()’
 1674 |         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
      |                                                                      ^

person Blue7    schedule 15.11.2019    source источник
comment
Разве это не работает? en.cppreference.com/w/cpp/utility/variant/index   -  person Eljay    schedule 15.11.2019
comment
std::variant‹Types...›::index возвращает нулевой индекс позиции, т.е. если вариант типа variant<int,float,bool> содержит логическое значение, индекс будет равен 2. Мне нужен индекс типа, который содержит хэш-код типа, который гарантированно будет согласованным во всем приложении, и имя типа, основанное на компиляторе.   -  person Blue7    schedule 15.11.2019
comment
Я думаю, что вижу. Вам нужно что-то вроде этого: en.cppreference.com/w/cpp/utility /вариант/вариант_альтернатива   -  person Eljay    schedule 15.11.2019
comment
Это выглядит многообещающе. Я уже не за компом, так что не могу попробовать. Как вы думаете, можно ли использовать это для создания моей функции get_held_type?   -  person Blue7    schedule 15.11.2019
comment
Я думаю, что это в правильном направлении. Но вас, вероятно, больше заинтересует ответ на этот вопрос SO: " title="получить текущий идентификатор типа стандартного варианта, такого как тип boostvariant"> stackoverflow.com/questions/53696720/   -  person Eljay    schedule 15.11.2019


Ответы (1)


std::visit удобен при работе со всеми альтернативами единообразно.

std::visit([](auto& v) -> std::type_index { return typeid(v); }, var)

Полная демонстрация:

#include <iostream>
#include <variant>
#include <string>
#include <typeindex>

using variant_t = std::variant<int, float, bool, double, std::string>;

int main() {
    variant_t var = 3.141;
    std::cout << std::visit([](auto& v) -> std::type_index { return typeid(v); }, var).name() << '\n';
}
person cpplearner    schedule 15.11.2019
comment
Вы можете использовать auto в лямбде с std::visit!? Очень круто. Спасибо. - person Blue7; 15.11.2019