I\'m using a std::tuple
and defined a class enum to somehow \"naming\" each of the tuple\'s fields, forgetting about their actual indexes.
So instead o
A completely different solution would be:
A& my_field(std::tuple<A,B>& t) { return std::get<0>(t); }
A const& my_field(std::tuple<A,B> const& t) { return std::get<0>(t); }
B& my_other_field(std::tuple<A,B>& t) { return std::get<1>(t); }
B const& my_other_field(std::tuple<A,B> const& t) { return std::get<1>(t); }
my_field(t) = blah;
my_other_field(t) = frob;
2018 update:
It's not a problem anymore. I did have a problem when I tried variations of "enum class int", but this now works fine with VS 2017 15.7.2
enum
{
WIDTH,
HEIGHT
};
std::get<HEIGHT>( Remaining ) = std::get<HEIGHT>( Remaining ) - MinHeight;
My solution is to use:
namespace Something{enum class Something {MY_INDEX_NAME = 0,OTHER_INDEX_NAME};};
Yes, this was a bug in GCC 4.5. Scoped enums don't have implicit conversions to integral types.
The strongly-typed enums introduced by C++11 cannot be implicitly converted into integral values of type say int
, while std::get
expects the template argument to be integral type.
You've to use static_cast
to convert the enum values:
std::cout <<std::get<static_cast<int>(Bad::BAD)>(tup)<< std::endl; //Ok now!
Or you can choose to convert into underlying integral type as:
//note that it is constexpr function
template <typename T>
constexpr typename std::underlying_type<T>::type integral(T value)
{
return static_cast<typename std::underlying_type<T>::type>(value);
}
then use it as:
std::cout <<std::get<integral(Bad::BAD)>(tup)<< std::endl; //Ok now!
I'd like to add another answer because the original poster asked for a way to have a named access to elements of std::tuple through a class enum.
It is possible to have a template argument of the type of a class enum (at least in GCC). This makes it possible to define your own get
retrieving the element of a tuple given a class enum value. Below is an implementation casting this value to int, but you could also do something more fancy:
#include <tuple>
enum class names { A = 0, B, C };
template< names n, class... Types >
typename std::tuple_element<static_cast< std::size_t >( n ), std::tuple<Types...> >::type&
get( std::tuple<Types...>& t )
{
return std::get< static_cast< std::size_t >( n ), Types... >( t );
}
int main( int, char** )
{
std::tuple< char, char, char > t( 'a', 'b', 'c' );
char c = get<names::A>( t );
}
Note that std::get has two more variants (one for const tuple&
, one for tuple&&
), which can be implemented exactly the same way.