1

How can I get the get the std::typeindex of the type currently help by a variant in c++?

Say I have a variant:

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

I want to be able to create the function:

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

This is just for curiosity, I know that this is not the usual way to handle data in a variant.

If I add another type tovariant_t, I do not want to have to change any other code. i.e, the types need to be self registering.

Here is my attempt so far. I cheat a bit, as I use a map instead of a function, and an object has to be constructed in order to register the types at run time.

#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;

}

But this fails with gcc with the compiler error:

/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))...)
      |                                                                      ^
Blue7
  • 1,750
  • 4
  • 31
  • 55
  • Doesn't this work? https://en.cppreference.com/w/cpp/utility/variant/index – Eljay Nov 15 '19 at 17:24
  • std::variant::index return the zero based index of the position, i.e if a variant of type `variant` held a bool, the index would be 2. I want the type index, which contains a hash code of the type that is guaranteed to be consistent across the application, and a compiler based name for the type. – Blue7 Nov 15 '19 at 17:25
  • I think I see. You want something more like this: https://en.cppreference.com/w/cpp/utility/variant/variant_alternative – Eljay Nov 15 '19 at 17:28
  • That looks promising. I'm not by a computer anymore so I can't try it out. Do you think this could be used to create my 'get_held_type' function? – Blue7 Nov 15 '19 at 17:35
  • I think it is in the right direction. But you'll probably be more interested in the answer to this SO question: https://stackoverflow.com/questions/53696720/get-currently-held-typeid-of-stdvariant-like-boostvariant-type – Eljay Nov 15 '19 at 17:39

1 Answers1

5

std::visit is handy when dealing with all alternatives in a uniform way.

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

Full demo:

#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';
}
cpplearner
  • 13,776
  • 2
  • 47
  • 72