2

I might be a little dense but cannot understand what below lines do?

class background_task
{
  public:
    void operator()() const
    {
      do_something();
      do_something_else();
    }
};

background_task f;
std::thread my_thread(f);
  1. I realize a thread (named my_thread) is created which calls object f of class background_task but when is the function operator() in class background_task actually called?

  2. Why is overloading of the function operator required?

  3. I understand this is C++ 101 or very basic, but I still cannot grasp it, so which books should I refer to in order to learn more about such topics of C++.

bitmask
  • 32,434
  • 14
  • 99
  • 159
Mike J
  • 21
  • 3
  • 5
  • 1
    this is not about [operator overloading](http://stackoverflow.com/q/4421706/1025391), but about c++ functors. See this post: http://stackoverflow.com/a/356993/1025391 for a detailed answer to your question. – moooeeeep Apr 11 '12 at 17:44
  • 1
    Don't worry; this is not C++ 101. An introductory C++ class certainly wouldn't cover threads, probably wouldn't cover custom function-call operators, and might not even cover writing your own classes. – Rob Kennedy Apr 11 '12 at 18:30

2 Answers2

2

This definition of operator()()

class background_task
{
public:
void operator()() const
{
  do_something();
  do_something_else();
}
};

means that you can instantiate a background_task and call it (without any arguments in this case). That makes it a "callable entity":

background_task f;
f(); // calls foo::operator ()(), i.e calls do_something() and do_something_else().

As for the thread, it needs a callable entity that takes no parameters, so passing it an instance of a background_task is fine. If background_task wasn't callable the following wouldn't compile:

background_task f;
std::thread my_thread(f);

The std::thread constructor also allows you to pass the arguments of the callable entity if it has parameters, so for example

class background_task
{
public:
void operator()(double x) const
{
  // do something with x, if you want
  do_something();
  do_something_else();
}
};

would work with

background_task f;
std::thread my_thread(f, 3.1416);

internally, the thread will do the equivalent of calling f(3.1416).

Edit: Originally I claimed there was no overloading involved. That isn't completely clear so I rephrased my answer.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Well, although it is technically wrong, it seems to be common practice to refer to a custom operator implementation as "operator overloading". Sadly, spoken language doesn't always make sense. – bitmask Apr 11 '12 at 17:51
  • @bitmask now you've got me thinking. Maybe it is overloading after all, if you consider you are overloading an operator void(void) in this case, as opposed to overloading something thathas already been defined for a particular type... – juanchopanza Apr 11 '12 at 17:55
  • The first implicit parameter (`this`) always determines the function to be called. I wouldn't say `void X::foo()` and `void Y::foo()` are overloads of `foo` although they have the same name and differ only in the (logical) arguments. The same reasoning would apply to `void operator()() const`. But I'm nitpicking :) – bitmask Apr 11 '12 at 18:02
  • @bitmask I guess one could argue that it is void(X*) and void(X*), i.e. overloads of operators that take a pointer to something and return void. – juanchopanza Apr 11 '12 at 18:33
1
  1. The thread object std::thread(f, a, b, c) makes a copy of the object f (let's call it copy_of_f), and the entry point of the new execution context is the call copy_of_f(a, b, c) (or more verbosely, copy_of_f.operator()(a, b, c)).

  2. The object f must be a callable entity, which means that the expression f(a, b, c) must make sense.

  3. Books specifically on C++11 are still in the process of being written. Look out for Stroustrup, Meyers and others later this year. Till then, the internet is probably your best bet.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084