Reputation: 109
I have a std::tuple
of std::map
containers that is defined by a variadic template like so:
template <typename KeyType, typename... ValueTypes>
class TupleMaps
{
public:
template<typename T>
using MapType = std::map<KeyType, T>;
std::tuple<MapType<ValueTypes>...> member_tuple;
}
I want to get the appropriate map from the tuple by its value type and I thought I could implement a member function such as:
MapType<ValueType>& getMap() { std::get<MapType<ValueType>>(member_tuple); }
but was stopped when attempting to put together something like
TupleMaps<int, float, std::string> maps;
if (maps.getMap<float>().size() !=0) { ... };
by the compiler error "no matching function for call to get()"
.
What is the appropriate way to extract the correct element from a tuple by type in this case?
Upvotes: 2
Views: 181
Reputation: 66200
As explained by NathanOlivier, get<type>(tupleValue)
is a C++14 feature.
If you use a C++11 compiler, a solution can be to write a type traits to select the index of a type in a list.
By example
template <typename T, typename T0, typename ... Ts>
struct getI
{ static constexpr std::size_t value { 1U + getI<T, Ts...>::value }; };
template <typename T, typename ... Ts>
struct getI<T, T, Ts...>
{ static constexpr std::size_t value { 0U }; };
So you can write your getMap<type>()
methods as follows
template <typename T>
MapType<T> & getMap ()
{ return std::get<getI<T, ValueTypes...>::value>(member_tuple); }
template <typename T>
MapType<T> const & getMap () const
{ return std::get<getI<T, ValueTypes...>::value>(member_tuple); }
The following is a full working example
#include <map>
#include <tuple>
#include <iostream>
template <typename T, typename T0, typename ... Ts>
struct getI
{ static constexpr std::size_t value { 1U + getI<T, Ts...>::value }; };
template <typename T, typename ... Ts>
struct getI<T, T, Ts...>
{ static constexpr std::size_t value { 0U }; };
template <typename KeyType, typename ... ValueTypes>
struct TupleMaps
{
template<typename T>
using MapType = std::map<KeyType, T>;
std::tuple<MapType<ValueTypes>...> member_tuple;
template <typename T>
MapType<T> & getMap ()
{ return std::get<getI<T, ValueTypes...>::value>(member_tuple); }
template <typename T>
MapType<T> const & getMap () const
{ return std::get<getI<T, ValueTypes...>::value>(member_tuple); }
};
int main ()
{
TupleMaps<int, float, std::string> maps;
std::cout << maps.getMap<float>().size() << std::endl; // print 0
maps.getMap<float>()[3] = 7.5;
std::cout << maps.getMap<float>().size() << std::endl; // print 1
}
Upvotes: 2
Reputation: 180630
std::get<type>
was added to C++ in C++14. In C++11 you could only use std::get<index>
.
You will either have to compile with C++14 enabled or write your own version of get
if you have to use C++11
Upvotes: 2