23

I'm currently studying boost threads. And I came across that the thread class has a constructor that accepts callable objects. What are callable objects?

class CallableClass
{
private:
    // Number of iterations
    int m_iterations;

public:

    // Default constructor
    CallableClass()
    {
        m_iterations=10;
    }

    // Constructor with number of iterations
    CallableClass(int iterations)
    {
        m_iterations=iterations;
    }

    // Copy constructor
    CallableClass(const CallableClass& source)
    {
        m_iterations=source.m_iterations;
    }

    // Destructor
    ~CallableClass()
    {
    }

    // Assignment operator
    CallableClass& operator = (const CallableClass& source)
    {
        m_iterations=source.m_iterations;
        return *this;
    }

    // Static function called by thread
    static void StaticFunction()
    {
        for (int i=0; i < 10; i++)  // Hard-coded upper limit
        {
            cout<<i<<"Do something in parallel (Static function)."<<endl;
            boost::this_thread::yield(); // 'yield' discussed in section 18.6
        }
    }

    // Operator() called by the thread
    void operator () ()
    {
        for (int i=0; i<m_iterations; i++)
        {
            cout<<i<<" - Do something in parallel (operator() )."<<endl;
            boost::this_thread::yield(); // 'yield' discussed in section 18.6
        }
    }

};

How does this become a callable object? Is it because of the operator overloaded or the constructor or something else?

user2052436
  • 3,309
  • 1
  • 19
  • 32
Xegara
  • 443
  • 2
  • 9
  • 21
  • 2
    It's because `operator()`, yes. See [here](http://stackoverflow.com/questions/356950/c-functors-and-their-uses). In addition "callable objects" in this contexts are also, functions, function pointers and lambda functions. – jrok Oct 09 '13 at 17:11
  • 1
    It's the overloaded `operator()`. It lets you call an instance of that class like a function. They're called *functors*, *function objects*, *callable objects*, etc. – Simple Oct 09 '13 at 17:11
  • 2
    You should tag (and name) this question with boost. Boost is not a standard C++ library, so the very large boost community here might be able to pick this up faster if you tagged and named it properly. –  Oct 09 '13 at 17:34

7 Answers7

23

A callable object is something that can be called like a function, with the syntax object() or object(args); that is, a function pointer, or an object of a class type that overloads operator().

The overload of operator() in your class makes it callable.

Mike Seymour
  • 235,407
  • 25
  • 414
  • 617
6

There are two steps here. In the C++ Standard, a "function object" is an object that can appear on the left-hand side of a parenthesized argument list, i.e, a pointer to function or an object whose type has one or more operator()s. The term "callable object" is broader: it also includes pointers to members (which can't be called with the normal function call syntax). Callable objects are the things that can be passed to std::bind etc. See 20.8.1 [func.def] and 20.8[function.objects]/1.

Pete Becker
  • 69,019
  • 6
  • 64
  • 147
4

An object which has at least an overloaded operator() is a callable object, and that operator plus its object can be invoked like function invoking:

CallableClass obj;
obj();
masoud
  • 51,434
  • 14
  • 119
  • 190
  • I think that "callable object" has a broader definition than just this, but I can't find a reference. To be sure, a class with an `operator()` *is* a callable object -- I'm just not certian the reverse is true. – John Dibling Oct 09 '13 at 17:23
  • @JohnDibling: Yes, and I said "An object ... _is_ a callable object" not in the reverse. – masoud Oct 09 '13 at 17:29
  • @JohnDibling - you're right: "callable object" includes pointer to member. Things that can be called with a parenthesized argument list are function objects. – Pete Becker Oct 09 '13 at 18:13
  • 1
    @JohnDibling effective modern c++,1st edition,five print or standard c++ library,second edition,3rd print – Tu Xiaomi Jan 08 '16 at 01:55
4

A callable object is an object instance from a class with operator() overloaded:

struct Functor {
    ret_t operator()();
    // ...
}

Functor func;  // func is a callable object

or a dereferenced-function pointer:

ret_t func() {
   // ...
}

func;  // func converts to a callable object
Paul Evans
  • 26,111
  • 3
  • 30
  • 50
  • _"A function is not an object... (§1.8/1)"_ – masoud Oct 09 '13 at 17:21
  • 1
    @MM.: Which is why the answer says "a function *pointer*", not "a function". Perhaps the code comment could be more precise, e.g. "func converts to a callable object". – Mike Seymour Oct 09 '13 at 17:23
  • @MikeSeymour: Indeed _function pointer_ is an object, but it's not callable. In fact, a dereferenced-function-pointer is callable, IMO. Am I right? – masoud Oct 09 '13 at 17:32
  • @MM. - a function pointer is callable: `f(3)`. Don't get into the details of whether a function pointer has to be dereferenced. `(*******f)(3)`, where `f` is a function pointer, is valid. – Pete Becker Oct 09 '13 at 17:42
2

Since C++17, a Callable object is actually defined by the standard; see https://en.cppreference.com/w/cpp/named_req/Callable for details.

HolyBlackCat
  • 45,832
  • 5
  • 81
  • 134
Carlo Wood
  • 3,402
  • 26
  • 39
1

Function object add member function pointers yields what are known as callable objects. When we in c++ 98/03,we use the class override the operator() as function.In general, we call that class function.It has the advantage of storing state of the function and other function can't.So it is the most important concept.And border, we call this style class function and other c style function and pointer to c style function "function object". The callable object is just "callable" object. It include function object and member function pointers.

Tu Xiaomi
  • 61
  • 8
1

In C++11, a callable element can be either:

  • A function pointer,
  • A member function pointer, (it is different from the previous one, check here)
  • An object of a functor class (a class wherein its operator() is implemented),
  • Anonymous functions (Lambdas),
  • Or any of the mentioned elements wrapped in a std::function object.

This means that you can use each of the mentioned callable elements to launch a std::thread. Take a look at the following sample code:

std::vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

int func()
{
   return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
}

class A
{
public:
   int mem_func() 
   { 
      return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
   }
};

class B
{
public:
   int operator()()
   {
      return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
   }
};

auto lambda = []() { return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); };


void main()
{
   A a;
   B b;

   std::function<int()> f1 = &func;
   std::function<int()> f2 = std::bind(&A::mem_func, &a);
   std::function<int()> f3 = std::bind(&B::operator(), &b);
   std::function<int()> f4 = lambda;

   std::thread t1 = std::thread(func);
   std::thread t2 = std::thread(&A::mem_func, a);
   std::thread t3 = std::thread(&B::operator(), b);
   std::thread t4 = std::thread(lambda);

   std::thread t5 = std::thread(f1);
   std::thread t6 = std::thread(f2);
   std::thread t7 = std::thread(f3);
   std::thread t8 = std::thread(f4);

   t1.join();
   t2.join();
   t3.join();
   t4.join();
   t5.join();
   t6.join();
   t7.join();
   t8.join();
}
Gupta
  • 7,679
  • 4
  • 29
  • 56