
on Sun Nov 16 2008, "Joachim Faulhaber" <afojgo-AT-googlemail.com> wrote:
I have found an article of Scott Meyers on his "most important general design guideline in my arsenal":
"Make interfaces easy to use correctly and hard to use incorrectly" (Mietucahatuin ;-) http://www.aristeia.com/Papers/IEEE_Software_JulAug_2004_revised.htm
I am still not convinced to pass my functors by value and I think it violates Mietucahatuin.
(1) It makes additional assumptions: The client of the software has to be aware, that passing a fat functor causes expensive copies, not only at the point of passing the functor to a library function but also in internal calls. That means she has to have knowledge about implementation details of the library code. That is a violation of the principle of information hiding.
(2) The client of the software has to remember complex knowledge in order to use the code correctly: If she wishes to use a rich state she has to remember to implement the functor using the pimpl idiom or move semantics. Yet Scott Meyers writes in the article above, and I think he's right: "But interfaces that rely on clients remembering to do something are easy to use incorrectly."
Except that there's a well-known convention that function objects and iterators (and probably some other things) should be lightweight-copyable.
(3) Passing functors by value stands in direct contradiction to the well established rule to pass class obects by (const)-reference.
That rule is wrong when objects need to be copied anyway. Pass-by-value + swap (or move) into place is the best practice in that case, because it saves copies of rvalues on known real compilers and costs no extra copies of lvalues.
(4) It takes the burden of facilitating correct use away from the libraries author and puts it on the libraries client, which also violates Meyer's Mietucahatuin-rule.
Sorry if I've got too apodictic. I am mainly interested in a good decision for my own library code.
A good choice that is both forward-looking and compatible with legacy code is to implement and document move semantics support (or a swappability requirement), and pass by value unless there's no need for an eventual copy.
As written earlier in this thread, I would prefer to pass functors const reference, and without additional wrappers (which is done by other boost libraries too). I do not call std::algorithms internally.
Please tell me, if there are strong arguments against that.
Extra copies of rvalues can be expensive, and function objects are often rvalues. -- Dave Abrahams BoostPro Computing http://www.boostpro.com