|
Boost : |
Subject: Re: [boost] Design conventions; passing functors
From: David Abrahams (dave_at_[hidden])
Date: 2008-11-11 02:58:59
on Thu Nov 06 2008, "Joachim Faulhaber" <afojgo-AT-googlemail.com> wrote:
> Hi,
>
> I am pondering about functor passing. Functors occur in my
> library (ITL) e.g. for the aggregation of associated values
> on insertion in interval_maps (aggregation on overlap):
>
> template<class Domain, class Codomain, ...>
> class interval_map{
> ...
> //(1) My current implementation is this:
> // Combinator is the aggregating functor template,
> // instantiated at compiletime
> template<template<class>class Combinator>
> interval_map& add(const value_type& value_pair)
> { /*Combinator template passed or instantiated somewhere*/ }
> ...
> }
>
> //I like this definition, because it's abstract:
> // The functor has to be a matching template e.g. inplace_max
> interval_map<int,int> m;
> m.add<inplace_max>(some); //(1)
>
> template<class Domain, class Codomain, ...>
> class interval_map{
> //(2) The more traditional definition
> template<class Combinator>
> interval_map& add(const value_type& value_pair)
> { /*Combinator type passed or called somewhere*/ }
> ...
>
> m.add<inplace_max<int> >(some); //(2)
>
> I prefer (1) but both definitions (1) and (2) are purely
> static denotations. To have adaptable functors or functors
> that can have states, like in ...
Try a unary MPL lambda expression here instead:
m.add<inplace_max<_> >(some);
> m.add(some, max_under(42));
>
> ... I am afraid I have to say sayonara to definition (1)
> and use this instead:
>
> template<class Domain, class Codomain, ...>
> class interval_map{
> //(3) Adaptable functor
> template<template<class>class Combinator>
> interval_map& add(const value_type& value_pair,
> const Combinator<Codomain>& combine)
> { /*combine functor passed or called somewhere*/ }
Presumably because you want to support stateful combine functions?
> Now, there seems to be a convention from the STL that functors
> shall be passed BY VALUE.
Ja.
> template<template<class>class Combinator>
> interval_map& add(const value_type& value_pair,
> Combinator<Codomain> combine);
>
> This is stated in [Sutter & Alexandrecu 2005, C++ Coding
> Standards] item 89:
> "Function objects are modeled on function pointers. Like
> function pointers, the convention is to pass them by value.
> All of the standard algorithms pass objects by value, and
> your algorithms should too."
>
> I do not really understand this convention and feel some
> resistance to follow it. In addition the call by value
> implementation can (and will) lead to heavy inefficiency
> by unaware usage of fat functors.
Sounds like a job for move semantics.
> So I browsed through
> some boost libraries and found that functors are passed by
> reference there (e.g. accumulators, fusion).
Look for "move.hpp" headers in various library subdirectories :-)
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk