• Advertisement
Sign in to follow this  

binary functions

This topic is 4043 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I don't understand how deriving classes from binary_function:
#include <functional>
template<class Arg1, class Arg2, class Result>
       struct binary_function {
       typedef Arg1 first_argument_type;
       typedef Arg2 second_argument_type;
       typedef Result result_type;
       };

and giving them a () operator makes them behave as a function pointer (that gets two inputs and returns an output). Could someone explain? Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Your class doesn't need to be derived from binary_function to have a working () operator.

That said, library writers might want to "know" what types is your function/functor operating on/returning. So they are asking for embeeded typedefs of your class - result_type, first_argument_type, etc. It is true that you could define the necessary types yourself, but there are more tricks that are possible only by deriving from a fixed class that everybody use.

For example, library writers might want to do some nifty tricks based on function's arity:


template< typename Functor >
void do_unary_or_binary(MyClass & obj, Functor f)
{
if (/*f is unary*/)
f(obj);
else if (/*f is binary*/)
f(obj, some_other_obj);
};



This will probably crash miserably, if f could not be called with one parameter AND with two parameters.

You can use overloading to make do_unary_or_binary work, knowing base class of the functor. (No, template specialisation will not work here at all.)


struct unary_tag {};
struct binary_tag {};

template<class Arg1, class Result>
unary_tag get_function_tag(const unary_function<Arg1,Result> &)
{ return unary_tag(); };

template<class Arg1, class Arg2, class Result>
binary_tag get_function_tag(const binary_function<Arg1,Arg2,Result> &)
{ return binary_tag(); };

template<class Arg1, class Result>
unary_tag get_function_tag( Result (*f)(Arg1) )
{ return unary_tag(); };

template<class Arg1, class Arg2, class Result>
binary_tag get_function_tag( Result (*f)(Arg1,Arg2) )
{ return binary_tag(); };


template< typename Functor >
void do_unary_or_binary_impl(MyClass & obj, Functor f, unary_tag)
{
// can safely assume Functor is unary.
f(obj);
};
template< typename Functor >
void do_unary_or_binary_impl(MyClass & obj, Functor f, binary_tag)
{
// can safely assume Functor is binary.
f(obj, some_other_obj);
};

template< typename Functor >
void do_unary_or_binary(MyClass & obj, Functor f)
{
do_unary_or_binary_impl(obj, f, get_function_tag(f));
};

Share this post


Link to post
Share on other sites
The thing that makes a function object behave as a function is just overloading operator(). operator() is just like any other operator or method a class can overload; it just happens to make calling the method use the same syntax as is used for calling a function.

The standard library's template algorithms (and similiar generic code) sometimes need to know the types that operator() uses. unary_function and binary_function provide standard names for the types and a concise way to define them (by inheriting from unary_function or binary_function with the types declared as the template parameters).

Share this post


Link to post
Share on other sites
They don't behave as a function pointer. Indeed, if you try to pass them to a function pointer you'll get errors (pretty sure anyways). They can however be called identically to common functions, so when passed into a template, the glorified string-replacement produces still-functional code.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement