patterncppMinor
C++ tuple implementation with get as a member
Viewed 0 times
withtuplegetmemberimplementation
Problem
If you're familiar with std::tuple, you're aware that accessing its elements is slightly unusual. Instead of using a member function, we're provided with the function
We would expect:
but apparently we would have to write:
(a source, see footnote 5).
This seemed like a bad case of "I heard that she heard that he heard...", because I was unable to find an implementation of a tuple that exposed this ugliness by including get as a member. I heard that Boost's tuple had get as a member, but after inspecting the source I discovered that it also only accepted 10 elements max. It was time for me to implement it myself!
This functions as expected, and after some brief testing I found that there were no issues with storing pointers or references. But there was no need to write "template" for every call to get! (My compiler is GCC, by the way.)
Is there a reason why
std::get instead. I was curious as to why this is, so I conducted a brief search. The few websites that I saw all gave the same reason: the code used to called the method is ugly.We would expect:
my_tuple.get()but apparently we would have to write:
my_tuple.template get()(a source, see footnote 5).
This seemed like a bad case of "I heard that she heard that he heard...", because I was unable to find an implementation of a tuple that exposed this ugliness by including get as a member. I heard that Boost's tuple had get as a member, but after inspecting the source I discovered that it also only accepted 10 elements max. It was time for me to implement it myself!
template
class Tuple
{
};
template
struct TypeHolder;
template
struct TypeHolder>
{
typedef typename TypeHolder>::type type;
};
template
struct TypeHolder>
{
typedef R type;
};
template
class Tuple : public Tuple
{
public:
Tuple(T obj, Ts... objs)
: Tuple{ std::forward(objs)... }
, obj{obj}
{
}
template
typename std::enable_if>::type&
>::type get()
{
return obj;
}
template
typename std::enable_if>::type&
>::type get()
{
return static_cast*>(this)->get();
}
protected:
T obj;
};This functions as expected, and after some brief testing I found that there were no issues with storing pointers or references. But there was no need to write "template" for every call to get! (My compiler is GCC, by the way.)
Is there a reason why
std::tuple was not implemented in this way? I would like to know about any glaring flaws with this code before I move forward with it.Solution
Your source is not very specific as to why/when
If you have code like this:
That is fine, because all template arguments to
This however
generates a compiler error, because when
Your code sadly does not solve this problem and I don't think it is solvable.
Additionally I noticed that your
my_tuple.template get() is required.If you have code like this:
Tuple x(1,2,3);
int i = x.get();That is fine, because all template arguments to
Tuple are known at the time of parsing and Tuple is instantiated immediately, before the call to get is parsed. At that point the compiler already knows that in that specific instantiation of Tuple get is member function template rather than a non-template member and everything is ok.This however
template
auto foo(T t) {
Tuple x(t,2,3);
return x.get();
}generates a compiler error, because when
foo is parsed, the actual type of T is not known and instantiation of Tuple needs to be delayed until instantiation of foo. This means that when x.get is parsed, the compiler does not yet know what kind of language construct get is in the instatiation of Tuple and in fact it may very well vary for different T. Therefore it is assumed that get is a non-template member, which doesn't make sense considering the following template argument list.Your code sadly does not solve this problem and I don't think it is solvable.
Additionally I noticed that your
Tuple is an empty class if an empty type list is given. That is a bit inconsistent. I think at least get should be provided as empty function. Calling it should not be allowed, but referring to the member function should be fine.Code Snippets
Tuple<int, double, float> x(1,2,3);
int i = x.get<0>();template<typename T>
auto foo(T t) {
Tuple<T,int,double> x(t,2,3);
return x.get<0>();
}Context
StackExchange Code Review Q#142462, answer score: 4
Revisions (0)
No revisions yet.