4

I have been looking at some of the Boost source code and noticed they implement templated functions by using a functor instead of a plain function? Is there a reason for this?

For example:

template<typename Foo, typename Bar>
struct functor {
    Bar operator()(const Foo& foo) {
        return foo.as_bar();
    }
};

as opposed to:

template<typename Foo, typename Bar>
Bar func(const Foo& foo) {
    return foo.as_bar();
}

The only advantage I can come up with is it allows classes to inherit the function?

maddisoj
  • 576
  • 6
  • 16

1 Answers1

2

There are two main reasons: The first is, as pythonic metaphor noted, partial specialization is only valid for classes and not functions. Note that functions can use overloads to overcome this problem generally, but often if you are doing metaprogramming it's easier and more generic to use partial specialization. I'd actually think this was the main reason.

The second reason is that anytime that code wants to accept a function object (like in the STL, e.g. std::transform), it will have a type template parameter. If you pass a functor or a lambda, the exact type is known at compile time, and you don't pay for indirection, and inlining can be performed. If you pass a function pointer (or a std::function), only the signature is known at compile time, and you pay for an indirection (and you can't inline). For instance, std::sort can be considerably faster with a functor than a function pointer.

Note that there is a little used feature called function pointer template parameters; these are non type template parameters that specialize on a specific function, and thus can remove indirection. However, if you use one of these, you can't use a functor at all. So most code that wants to accepts a function object does it the way I described above.

Nir Friedman
  • 17,108
  • 2
  • 44
  • 72
  • The specifics of what I was looking at was a way for defining conversions between colour spaces, so I would suspect it was indeed to allow partial specializations. However, from what I have read It seems that using a functor is always the better choice? – maddisoj Jul 11 '15 at 16:45
  • Always is a pretty strong term. Where did you read that? Functors have their advantages, but they're also more verbose. Overloads are also generally easier to reason about than partial specializations. Personally I'd start with functions, and use functors only if I had a need based on generic programming or performance. Boost does a lot of generic programming, and has to be more careful with performance considerations as they're a widely used library. Implementation complexity is the least important attribute for them. Your (and my) situation is usually different. – Nir Friedman Jul 11 '15 at 16:52
  • The always was my own inference. Thank you for your explanation. – maddisoj Jul 11 '15 at 16:55