4

In the documentation for boost.geometry it states

Note: prefer using x = bg::get:<0>(point1);
(as opposed to x = point1.get<0>();)

I have seen this elsewhere in the boost docs. My question is why? Is this a best-practices thing, a performance thing or some quirk? Is it a general rule or specific to this library?

sehe
  • 374,641
  • 47
  • 450
  • 633
mmdanziger
  • 4,466
  • 2
  • 31
  • 47
  • 1
    For an existing point type (provided by someone else), you can implement a free get function that acts on it, but you can't add a get member function, so it is more generic. – Marc Glisse Jan 21 '14 at 12:22
  • @MarcGlisse, but wouldn't an outside point type (if it is derived from the base class) necessarily have a `get` anyway? Is this the only reason? – mmdanziger Jan 21 '14 at 12:30
  • 2
    If `point1` has a dependant type then you also don't need to write `point1.template get<0>()`. – Simple Jan 21 '14 at 12:30

1 Answers1

14

It's not boost per se, but modern C++ API design.

  • By not requiring member functions, you can adapt your own classes and even third party library types to work with the boost Api of your choice. (This way you can e.g. make types from a third party library serializable to a Boost Serialization archive).

  • Also, by making the functions free functions, there is an improved decoupling of dependencies. E.g.: fusion/tuple.hpp doesn't need to depend on anything IO related, because the streaming operations are free functions, and hence can be declared (and defined) in a separate header: fusion/tuple_io.hpp.

  • It also helps encapsulation because by default the free functions aren't friends of the host class (and as such are unable to access private members).

  • free functions can "Do The Right Thing" based on ADL:

    using std::swap;
    swap(a, b); // will lookup `swap` in the namespaces that declare the parameter types
    

    (several other namespaces are also used for lookup)

  • Finally, free functions can generically service a group of types, that need not be OO-related (inheritance related). In this way, free functions encourage avoiding duplication of code.

Edit Addressing the question of why you should prefer the non-member syntax, if both exist:

  • it works for types that don't have the member function
  • it doesn't require .template disambiguation in template code (as pointed out by @Simple)
  • Again: it's not boost specific.

    • c++03 has had std::swap() as a free function
    • c++11 introduces std::begin() and std::end() as free functions
    • std::hash<>, std::less<>, std::greater<>, std::equal_to<> similarly provide customization points that are not intrusive (but aren't functions of course)
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Off topic: out of interest, what's the use case for customizing `std::less` in preference to free `operator<`? You're right that it provides a customization point, but I think it's a pretty obscure one: you want your type to be comparable by algorithms and containers, but not by code that normal human beings write ;-) Is there some annoying consequence of partial specialization that means sometimes you have to put up with that? – Steve Jessop Jan 21 '14 at 13:15
  • @SteveJessop The most annoying thing with free functions I can think of would be the [Pitfalls of ADL](http://stackoverflow.com/questions/2958648/what-are-the-pitfalls-of-adl), i.e. that ADL can also easily DoTheWrongThing(TM). There's no way to "control" ADL (other than to prohibit it). Yes, library writers can (and should) be defensive about this (by using ADL barrier namespaces). But function objects have the distinct property that they don't participate in ADL by definition. (I know Eric Niebler has advocated this and used it as a principle in designing Proto0x). – sehe Jan 21 '14 at 14:50
  • I don't know whether this was the design principle for the standard library. Perhaps they just wanted the ability to e.g. instantiate container types with a concrete comparator type, as opposed to having to initialize some kind of "generic function type" with a specific instance object on construction always. – sehe Jan 21 '14 at 14:50
  • yes, I see reasons for `std::less` to exist. It's just using it as the customization point for a user-defined type that I'm puzzled by: it's allowed but I don't think I've ever done it. – Steve Jessop Jan 21 '14 at 15:29