[BGL] why not breakup put_get_helper into three structs?

Hello, I posted this in gmane.comp.lib.boost.user and got no response, so I thought of reposting it here: Link: http://thread.gmane.org/gmane.comp.lib.boost.user/37318 Repost: Helllo, I was wondering why put_get_helper shouldn't be three structs (put_helper, get_helper, put_get_helper, with the latter deriving from from the formers) instead of one? My rationale is outlined below along with the proposed code. //Begin Rationale Problem: want a helper method for readable property maps. Solution1: use exist boost::put_get_helper and just never use the put function. Problem with solution 1: 1) the put function will still be "callable", and 2) calling the put function will result in an invalid assignment to a read-only variable compiler error, which is cryptic to decipher, ie, that even though the put function does exist it should not be called. The only way to clarify this would be via documentation, which then brings about the problem of keeping code in sync with comments. Solution2: make a helper method for readable property maps that won't make the put companion function a valid function call, ie, break up boost::put_get_helper to put_helper, get_helper, and put_get_helper which derives from the latter two. Problems with solution 2: None that I can see. Advantages of solution 2: 1) It's self-documenting whether the put or get functions are intended to be called, ie if I derive from get_helper then it's self-evident that I shouldn't be calling the put function (vice versa); and 2) given the above scenario, even if by chance the put function get's called the compiler error message will be easier to decipher, ie, something along the lines of: <no matching function for call to ‘put(...)'>. 3) Not really an advantage, but ... backward compatibility is maintained. //End Rationale. //Proposed code adapted from boost/property_map.hpp // A helper class for constructing a property map // from a class that implements operator[] template <class RetVal, class RvaluePropertyMap> struct get_helper { }; template <class LvaluePropertyMap> struct put_helper { }; template <class RetVal, class LvaluePropertyMap> struct put_get_helper : public put_helper<LvaluePropertyMap>, public get_helper<RetVal, LvaluePropertyMap> { }; template <class PropertyMap, class RetVal, class K> inline RetVal get( get_helper<RetVal, PropertyMap> const & pa, K const & k) { RetVal v = static_cast<const PropertyMap&>(pa)[k]; return v; } template <class PropertyMap, class K, class V> inline void put( put_helper<PropertyMap> const & pa, K k, V const & v) { static_cast<const PropertyMap&>(pa)[k] = v; } Thanks in advance, -Mostafa

I was wondering why put_get_helper shouldn't be three structs (put_helper, get_helper, put_get_helper, with the latter deriving from from the formers) instead of one? My rationale is outlined below along with the proposed code.
The put_get_helper is just something used internally to abbreviate the construction of lots of different property maps. However, building property maps is pretty trivial: it's just a structure with 1-3 operations and a couple of free functions. I don't really see the need for an expanded framework to help build them. You might also consider that the BGL is fairly dated and stagnant, and in need of some serious TLC. Whether or not property maps continue to exist in the same form in future renditions of the library is anybody's guess - I'm leaning towards "no". Andrew Sutton asutton@cs.kent.edu

However, building property maps is pretty trivial: it's just a structure with 1-3 operations and a couple of free functions.
I agree. But if I am going to write a property map class with operator[], then why should I have to write a global put, or a global get, or "global put and global get" when I can use template helper class(es) to automate that task for me. Rewriting very similar code is tedious and error-prone because it is tedious - I'm speaking from personal experience of writing put/get global functions and forgetting a const here or a reference there ... And the problem with forgetting references is that the compiler doesn't complain and I will potentially incur a runtime penalty which will be hard to track to down. (Just because something is trivial, doesn't negate the possibility that it will be tedious or error prone.) Currently if i want to avoid rewriting code that can easily be automated (via templates) I'm relegated to using put_get_helper which gives me both put AND get global functions. This is undesirable for reasons I've outlined in my rationale in my first post.
I don't really see the need for an expanded framework to help build them.
From a client's perspective it's not needed, but it will be very useful in helping to avoid missing reference mistakes and in reducing what needs to be coded.
As for an "expanded framework", what I'm proposing is pretty trivial change to existing code and what's more it's entirely backward compatible (<----**emphasis**), so no other preexisting code using BGL needs to be changed to accommodate my proposition.
You might also consider that the BGL is fairly dated and stagnant, and in need of some serious TLC. Whether or not property maps continue to exist in the same form in future renditions of the library is anybody's guess - I'm leaning towards "no".
Valid point. But if for the next release(s) of BGL no changes have been made to property maps, I would argue that my original proposition will be a non-trivial aide for clients of the library.

on Wed Aug 06 2008, Andrew Sutton <asutton-AT-cs.kent.edu> wrote:
I was wondering why put_get_helper shouldn't be three structs (put_helper, get_helper, put_get_helper, with the latter deriving from from the formers) instead of one? My rationale is outlined below along with the proposed code.
The put_get_helper is just something used internally to abbreviate the construction of lots of different property maps. However, building property maps is pretty trivial: it's just a structure with 1-3 operations and a couple of free functions. I don't really see the need for an expanded framework to help build them.
You might also consider that the BGL is fairly dated and stagnant, and in need of some serious TLC. Whether or not property maps continue to exist in the same form in future renditions of the library is anybody's guess - I'm leaning towards "no".
Hm, and what do you propose as an alternative? I can't see how we could do without them. I might like some trivial syntactic changes get(m, k) ==> m(k) put(m, k, v) ==> m(k,v) but that's about it. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

You might also consider that the BGL is fairly dated and stagnant, and in need of some serious TLC. Whether or not property maps continue to exist in the same form in future renditions of the library is anybody's guess - I'm leaning towards "no".
Hm, and what do you propose as an alternative? I can't see how we could do without them.
I might like some trivial syntactic changes
get(m, k) ==> m(k) put(m, k, v) ==> m(k,v)
but that's about it.
Basically, yeah. With the addition of lambda expressions, the put/get functions could basically disappear, and the act of building property maps becomes the art of writing lambda functions. At least, that's the theory. The concepts don't really change either. There can still a read, write, and lvalue concepts. They just appear as: m(k) // read m(k, x) // write m(k) = x // lvalue Or something like that. I have part of an implementation of new property maps in my SoC directory (sandbox/SOC/2008/graphs). Andrew Sutton asutton@cs.kent.edu

on Thu Aug 07 2008, Andrew Sutton <asutton-AT-cs.kent.edu> wrote:
You might also consider that the BGL is fairly dated and stagnant, and in need of some serious TLC. Whether or not property maps continue to exist in the same form in future renditions of the library is anybody's guess - I'm leaning towards "no".
Hm, and what do you propose as an alternative? I can't see how we could do without them.
I might like some trivial syntactic changes
get(m, k) ==> m(k) put(m, k, v) ==> m(k,v)
but that's about it.
Basically, yeah. With the addition of lambda expressions, the put/get functions could basically disappear, and the act of building property maps becomes the art of writing lambda functions. At least, that's the theory. The concepts don't really change either. There can still a read, write, and lvalue concepts. They just appear as:
m(k) // read m(k, x) // write m(k) = x // lvalue
Personally I don't think there should be an lvalue concept. Is there really an algorithm that requires it?
Or something like that. I have part of an implementation of new property maps in my SoC directory (sandbox/SOC/2008/graphs).
OK, but that's certainly not "property maps continue to exist in the same form...." Ugh, now that I copied your words out, I realize you said "the same" and not "some," which changes everything. Sorry for the noise. It pays to read carefully. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

The concepts don't really change either. There can still a read, write, and lvalue concepts. They just appear as:
m(k) // read m(k, x) // write m(k) = x // lvalue
Personally I don't think there should be an lvalue concept. Is there really an algorithm that requires it?
I was actually wondering the same thing as I wrote that. I don't think there are any algorithms that use it, and I can't think of any use cases where lvalue access is required beyond the usual get/put operations. Maybe the lvalue concept can go away until somebody comes up with a really good use for it.
OK, but that's certainly not "property maps continue to exist in the same form...." Ugh, now that I copied your words out, I realize you said "the same" and not "some," which changes everything. Sorry for the noise.
My original phrasing was poorly worded. I can certainly see where it seems like I don't like property maps. Andrew Sutton asutton@cs.kent.edu

On Aug 6, 2008, at 8:10 AM, Andrew Sutton wrote:
You might also consider that the BGL is fairly dated and stagnant, and in need of some serious TLC. Whether or not property maps continue to exist in the same form in future renditions of the library is anybody's guess - I'm leaning towards "no".
I'm going to have to disagree with pretty much all of this :) There are quite a few things in the BGL that I'd love to update and improve, but it's a solid piece of code that used in many different applications and is actively maintained. The property map concept is central to the use of the BGL and, while it has rough corners that we want to smooth over (especially: it needs to be easier for users and algorithms alike to create an efficient property map for any graph data structure), I think the core design and implementation of the BGL is quite solid. Similar to what Dave said, I would certainly want to consider making function objects into property maps (perhaps automatically), so that we can leverage the power of boost::bind, lambda/phoenix, and C++0x lambdas to compose property maps easily. But, I still think that can be done within the existing framework. I expect that what we'll be doing with the Boost.Graph version 2 work is modernizing the internals (now that we have MPL, enable_if, and such) and simplifying the external interface... but we'll be doing so while being careful not to break existing code too badly. - Doug
participants (4)
-
Andrew Sutton
-
David Abrahams
-
Doug Gregor
-
Mostafa