On 1/23/07, Joaquín Mª López Muñoz <joaquin@tid.es> wrote:
it might be a good idea to provide an additional
predefined
key extractor for use with free functions so as to supplement the existing
ones working with member functions, I'll add this to my to consider list.
Hope this helps,
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
I'm currently experimenting with a rule of thumb where my extensible template classes are all written using policies, but the default for each policy is one that calls a free function. Sort of a best of both worlds approach - or at least that's what I'm hoping. For example, intrusive_ptr could be rewritten to take an AddRef policy, and the default could be to call intrusive_ptr_add_ref, etc:
template <typename T>
struct intrusive_ptr_default_add_ref_policy
{
static void add_ref(T * t)
{
intrusive_ptr_add_ref(t);
}
};
template <typename T, typename AddRefPolicy = intrusive_ptr_default_add_ref_policy>
struct intrusive_ptr
{
intrusive_ptr(...)
{
...
AddRefPolicy::add_ref(t);
}
};
So user can implement intrusive_ptr_add_ref() OR implement a policy class.
Might not be worthwhile for intrusive_ptr but it's an easy example. Probably makes more sense for templates where you might actually want different behaviours for a particular type, in different contexts. Much like passing in a predicate to std::map<>, yet the default is std::less, which is based on the type's intrinsic operator<().
Speaking of map<> and std::less(), I kind of wish they added one extra point of abstraction there - something like std::order() or map_order() or key_order(), that was allowed to be overridden. The idea being that some types can have a meaningful order() when used as a key, that is different than the meaningful operator<(). In my case it was a string class consisting of shared static strings - so that, used as a key, they could be quickly compared using the actual pointer to the shared memory, so operator<() would be implemented using that method; but used as a typical string, you might want to order them aphabetically, so operator<() should be a lexigraphical compare. And yes, I could just make sure my map<> took a custom predicate, but I'd rather the string class control that 'intrinsic', and not have to police future uses of the class when used as a key, to ensure the right predicate is used.
The real answer probably is that std::map<> should call a free function, like, say, extract_key(T const & t), and then call the predicate on that, instead of on T.
Hey, which gets us right back to where we started - multi-index DOES have key-extraction (making it better than std::map<> already), and the OP is asking for it to be a free function! Now if we could only get std::map<> to use it...
Tony