58

boost::tuple has a get() member function used like this:

tuple<int, string, string> t(5, "foo", "bar");
cout << t.get<1>();  // outputs "foo"

It seems the C++0x std::tuple does not have this member function, and you have to instead use the non-member function form:

std::get<1>(t);

which to me looks uglier.

Is there any particular reason why std::tuple doesn't have the member function? Or is it just my implementation (GCC 4.4)?

Lii
  • 11,553
  • 8
  • 64
  • 88
HighCommander4
  • 50,428
  • 24
  • 122
  • 194

3 Answers3

72

From C++0x draft:

[ Note: The reason get is a nonmember function is that if this functionality had been provided as a member function, code where the type depended on a template parameter would have required using the template keyword. — end note ]

This can be illustrated with this code:

template <typename T>
struct test
{
  T value;
  template <int ignored>
  T&  member_get ()
  {  return value;  }
};

template <int ignored, typename T>
T&  free_get (test <T>& x)
{  return x.value;  }

template <typename T>
void
bar ()
{
  test <T>  x;
  x.template member_get <0> ();  // template is required here
  free_get <0> (x);
};
  • 18
    I see. Still, they could have provided both member and non-member functions like boost, if for no other reason that to be compatible with boost (since a lot of people are likely to have already been using boost tuples before switching to C++0x). – HighCommander4 Jul 22 '10 at 21:40
  • 1
    @HighCommander4 Whereas I understand your argument, boost compatibility alone is not a sufficient reason *on its own*, since compatibility to existing solutions shouldn't be *the only* driving force for providing something in a *new* standard and even boost is not the non-plus-ultra and may profit from some revision. Those general words being said, I still agree that member-`get`s would have been a good idea. – Christian Rau Oct 16 '12 at 08:13
  • 3
    Now that we have C++11 that no longer requiring template keyword, we can totally have a member function now? Just a proposal needed? – SwiftMango Dec 13 '18 at 19:48
33

The existing answers are great and certainly for the standards committee were vital for this purpose. But there is another issue that I think is important enough to mention.

With free functions, you have the ability to modify an interface without changing the definition of a class. You can make any type "gettable" simply by specializing the global get. With a member function, you would have to directly modify the class.

Range-based for looks for member begin/end on class types, but it also looks for non-member begin/end via ADL. These APIs can be used with any container, even those that don't have begin/end functions. You can specialize it for, for example, LibXML2 element types, such that you can range-based for over xmlElement*'s.

You can't do that if they had to be member functions.

In C++, free functions are a natural interface for many operations that could be done on many different kinds of classes.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 3
    `std::begin/std::end` are also good examples of how member and non-member functions can work together nicely. You can use either with most containers. – jakar May 13 '14 at 17:50
  • Ok this is cool and all but *provide the member function too!!* – qz- Aug 18 '21 at 04:06
15

N3090/3092, §20.4.2.6/8: "Note: The reason get is a nonmember function is that if this functionality had been provided as a member function, code where the type depended on a template parameter would have required using the template keyword. —end note"

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111