Home > database >  Unable to store an std::type_info object in an std::tuple
Unable to store an std::type_info object in an std::tuple

Time:12-02

I'm trying to initialize a tuple (using std::make_tuple), and I want to store an std::type_info in it as well, but I don't know why for some reason this simple looking piece of code doesn't compile.

I tried running the following code:-

#include <iostream>
#include <string>
#include <tuple>
#include <typeinfo>
#include <any>

int main()
{
    
    std::tuple<std::type_info, int, std::any> tpl = std::make_tuple(typeid(float), 1, "Hello");
    
    const auto&[type, num, anyval] = tpl;
    std::cout<<type.name()<<std::endl;
    std::cout<<num<<std::endl;
    std::cout<<std::any_cast<const char*>(anyval)<<std::endl;
    return 0;
}

If I only omit storing the first value (ie. type info) and create only std::tuple<int, std::any> there doesn't seem to be any problem, but this attempt fails. How to get around it, as I've to store the std::type_info object anyhow.

CodePudding user response:

Problem is that std::type_info do not have ANY constructors. No copy, no move or default constructors. So you can't copy this value. You can get only reference of it.

You can use std::reference_wrapper as a workarund:

int main()
{
    std::tuple<std::reference_wrapper<const std::type_info>, int, std::any> tpl = std::make_tuple(std::cref(typeid(float)), 1, "Hello");

    const auto& [type, num, anyval] = tpl;
    std::cout << type.get().name() << std::endl;
    std::cout << num << std::endl;
    std::cout << std::any_cast<const char*>(anyval) << std::endl;
    return 0;
}

https://godbolt.org/z/czobc3h57

As point out by StoryTeller there is std::type_index to address this issue in nicer way:

int main()
{
    std::tuple<std::type_index, int, std::any> tpl = std::make_tuple(std::type_index(typeid(float)), 1, "Hello");

    const auto& [type, num, anyval] = tpl;
    std::cout << type.name() << std::endl;
    std::cout << num << std::endl;
    std::cout << std::any_cast<const char*>(anyval) << std::endl;
    return 0;
}

https://godbolt.org/z/z5dv8Wf86

CodePudding user response:

I overlooked this, but now I've a solution which might be even better.

I skipped storing std::type_info (or std::type_index) at all. The third type (std::any) contains an std::type_info for the type it is enclosing, so storing it twice wouldn't be a good thing anyways.

Although the standard library does provide std::type_index which I didn't knew but came across while researching for this a bit.

  • Related