My basic idea was to derive my own class from std::tuple to get some helper types inside like this:
template <typename ... T>
class TypeContainer: public std::tuple<T...>
{
public:
using BaseType = std::tuple<T...>;
static const size_t Size = sizeof...(T);
TypeContainer(T... args):std::tuple<T...>(args...){};
using index_sequence = std::index_sequence_for<T...>;
};
Now I try to use the code as follows:
using MyType_tuple_with_empty = std::tuple< std::tuple<float,int>, std::tuple<>, std::tuple<int>>;
using MyType_typecontainer_with_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<>, TypeContainer<int>>;
using MyType_tuple_non_empty = std::tuple< std::tuple<float,int>, std::tuple<int>, std::tuple<int>>;
using MyType_typecontainer_non_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<int>, TypeContainer<int>>;
template <typename T>
void Do( const T& parms )
{
// The following lines result in errors if TypeContainer with
// empty element comes in. The empty element is in std::get<1> which
// is NOT accessed here!
std::cout << std::get<0>(std::get<0>(parms)) << " ";
std::cout << std::get<1>(std::get<0>(parms)) << std::endl;
std::cout << std::get<0>(std::get<2>(parms)) << std::endl;
}
int main()
{
MyType_tuple_with_empty p1{{ 1.2,3},{},{1}};
Do( p1 );
MyType_typecontainer_with_empty p2{{ 1.2,3},{},{1}};
Do( p2 ); // << this line raise the error
MyType_tuple_non_empty p3{{ 1.2,3},{4},{1}};
Do( p3 );
MyType_typecontainer_non_empty p4{{ 1.2,3},{4},{1}};
Do( p4 );
}
If I compile with Do(p2)
I get the following error:
error: no matching function for call to '
get(const TypeContainer<TypeContainer<float, int>, TypeContainer<>, TypeContainer<int> >&)
'
Can someone explain why the existence of an empty TypeContainer
in connection with std::get
will result in that problem?
Edit: Additional information:
The lines
MyType_tuple_with_empty p1{{{ 1.2,3},{},{1}}};
MyType_tuple_non_empty p3{{ 1.2,3},{4},{1}};
can not compiled with gcc5.2.0 but with gcc6.1.0. This is a bit mysterious because I remember that the constructor of the tuple is indeed explicit. Why this works with gcc6.1.0? But that is not the problem I search for :-)
Another hint: The code which I have problems with seems to compile with clang3.5.0.
A bit hard to understand...
Edit2: Digging through the error lists ( a long one :-) ) I found:
/opt/linux-gnu_5.2.0/include/c++/5.2.0/tuple|832 col 5| note: template argument deduction/substitution failed: main.cpp|104 col 45| note: '
std::tuple<_Elements ...>
' is an ambiguous base class of 'TypeContainer<TypeContainer<float, int>, TypeContainer<>, TypeContainer<int> >
' ||std::cout << std::get<0>(std::get<0>(parms)) << " "
;
Seems that in libg++ someone derives multiple times from any tuple type which seems to be a broken library. Searching for this topic brings me to: Empty nested tuples error
Is this really related? Same bug or a new one :-)
std::is_base_of_v<std::tuple<>, std::tuple<std::tuple<>>>
through private inheritance in the buggy implementation). Related Q: https://mcmap.net/q/684560/-is-an-implementation-of-std-tuple-allowed-to-fail-with-triggering-a-derived-to-base-conversion-for-empty-class-elements, showing your code should work and GCC was buggy – Freeness