0
#include <iostream> 
#include <boost/bind.hpp>

struct FCall3Templ {

  template<typename ARG1, typename ARG2>
  ARG1 operator()(ARG1 arg1, ARG2 arg2) {
    return arg1+arg2;
  }
};
int main() {
  boost::bind<int>(FCall3Templ(), 45, 56)(); // call 1
  boost::bind<double>(FCall3Templ(), 45.0, 56.0)(); // call 2
  return 0;
}

I'm posting the same code that you can find here .

I'm relatively new to meta-programming, boost::bind and operator overloading, but i don't get get what this code does in some portion of the code and i have this questions:

  • why using operator() without specifying the label for that operator? What is overloading/defining?
  • how i'm supposed to catch and store the value returned by the 2 calls using an assignment with T var = ? ?
  • what does it mean the fact that the last () is empty in both calls ? Is the call for the operator? So what is the name for this technique/operator?
  • why using the operator overloading this way and not using just a method?

Thanks.

Community
  • 1
  • 1
user827992
  • 1,743
  • 13
  • 25

2 Answers2

3

OK,first, the type FCall3Templ is a functor, and the two-parameter operator() means that you can create an instance and "call" it like this:

FCall3Templ f; // instantiate it
int i = f(45, 56); // call it, sums the numbers and returns the result

Next, boost::bind can be used to make another callable object, with a smaller number of parameters. In this case:

boost::bind<int>(FCall3Templ(), 45, 56);

it takes an FCall3Templ instance, and makes a functor that can be called without parameters, and that will do the same as calling f(45, 56). In other words, it "binds" the functor to two argument values. The last line is equivalent to, but not exactly the same, as

boost::bind<int>(f, 45, 56);

You capture the value by assigning the return value to a variable, like you would do with any function:

int n = boost::bind<int>(FCall3Templ(), 45, 56);

Finally, here we call a temporary instance of such a functor:

boost::bind<int>(FCall3Templ(), 45, 56)();

where the final () mean we are calling a no-parameter functor, and would be clearer if expressed like this (not tested):

boost::function<int()> f2 = boost::bind<int>(FCall3Templ(), 45, 56);
int n = f2();
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 1
    With C++11, the type argument (the `` in `bind`) is not needed. You can provide it if you want the bind expression to return a different type than the functor returns, which isn't the case here. I don't know if boost::bind does the same thing; I just mention it for the benefit of people who have C++11. – Pete Becker Aug 15 '12 at 21:21
  • @PeteBecker indeed, thanks. I use C++11 and haven't used boost.function for a while, so I decided to leave it as per the example. – juanchopanza Aug 15 '12 at 21:23
  • If you're not using C++11, `boost::bind` will rely on the `result_type` member of the functor that it is given, or the user must specify the result type explicitly. Note, function pointers don't have this problem as it can deduce them from the function pointer directly. – Dave S Aug 15 '12 at 21:48
  • @juanchopanza really good explanation, thank you, i just pick one random answer as the accepted one because i can't do in a different way, but i would love to pick both if i could, thanks. – user827992 Aug 16 '12 at 03:12
  • @DaveS thank you, references to C++11 are always appreciated for keeping things clear and portable :) – user827992 Aug 16 '12 at 03:14
  • @PeteBecker same as my previous comment on this :) – user827992 Aug 16 '12 at 03:15
3

Taking your questions in turn:

1) operator() is the () operator for an object. For example, if you look at the definition for std::less, it defines operator() to take two arguments and do a comparison, and return the result. This allows you to write

  bool foo(int a, int b)
    {
       std::less<int> compare;
       return compare(int a, int b);
    }

2) In this case, you could catch them like you normally would.

int i = boost::bind<int>(FCall3Templ(), 45, 56)(); // call 1     
double d = boost::bind<double>(FCall3Templ(), 45.0, 56.0)(); // call 2    

3) boost::bind is used to take a function-object (an object with operator() defined), function pointer, or member function pointer optionally along with arguments and returns a new function object (type of which is difficult to describe) that when invoked uses the bound arguments (and possible arguments during the invoke). See the documentation for boost::bind

In this case, the answer is simply calling boost::bind and then immediatly invoking the result. The second set of () are invoking the result. Since all of the arguments were bound at the time boost::bind was called, no additional arguments were necessary.

4) And the reason why was that the original question was asking how to make boost::bind choose the correct function template instantiation automatically. Unfortunately, when using function pointers (including template functions), boost::bind cannot perform overload resolution automatically, since it has to be passed a single function pointer as it's first argument, and it is not aware of the how to perform the overload resolution.

However, if given a single functor, and that function defines a templated member function operator() or even an overloaded operator (), it can perform the overload resolution when it is invoked.

Dave S
  • 20,507
  • 3
  • 48
  • 68