60

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)?

1
  • 7
    As a design rule of thumb, non-member functions are to be preferred anyway. Commented Jul 22, 2010 at 23:59

3 Answers 3

74

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); }; 
Sign up to request clarification or add additional context in comments.

3 Comments

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 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-gets would have been a good idea.
Now that we have C++11 that no longer requiring template keyword, we can totally have a member function now? Just a proposal needed?
34

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.

2 Comments

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.
Ok this is cool and all but provide the member function too!!
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"

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.