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 of doing this:
std::tuple<A,B> tup;
/* ... */
std::get<0>(tup) = bleh; // was it 0, or 1?
I did this:
enum class Something {
MY_INDEX_NAME = 0,
OTHER_INDEX_NAME
};
std::tuple<A,B> tup;
/* ... */
std::get<Something::MY_INDEX_NAME> = 0; // I don't mind the actual index...
The problem is that, as this compiled using gcc 4.5.2, I've now installed the 4.6.1 version, and my project failed to compile. This snippet reproduces the error:
#include <tuple>
#include <iostream>
enum class Bad {
BAD = 0
};
enum Good {
GOOD = 0
};
int main() {
std::tuple<int, int> tup(1, 10);
std::cout << std::get<0>(tup) << std::endl;
std::cout << std::get<GOOD>(tup) << std::endl; // It's OK
std::cout << std::get<Bad::BAD>(tup) << std::endl; // NOT!
}
The error basically says that there's no overload that matches my call to std::get
:
test.cpp: In function ‘int main()’:
test.cpp:16:40: error: no matching function for call to ‘get(std::tuple<int, int>&)’
test.cpp:16:40: note: candidates are:
/usr/include/c++/4.6/utility:133:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/utility:138:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/tuple:531:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&)
/usr/include/c++/4.6/tuple:538:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&)
So, is there any way I can use my enum class as a template argument to std::get
? Was this something that wasn't ment to compile, and was fixed in gcc 4.6? I could use a simple enum, but I like the scoping properties of enum classes, so I'd prefer to use the latter if it's possible.
std::get
needs:struct foo { enum { bar }; };
and thenstd::get<foo::bar>(baz)
. (However none of the enumerators can have the same name as the struct they're in.) – Croftstruct { A my_index_name; B other_index_name; };
so you do not have to usestd::get<x>(tuple)
. Do not over-engineer this. Since you are introduce this enums this indicates you are trying naming fields in tuple, this implies you should use regular structs. – Anabelle