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.