📖
Go C++
  • Introduction
  • Chapter 1: What You Must Know First
    • Virtual Address Space of Process: Memory Partition and Layout
    • Function Call: Stack Frame
    • Program Compiling and Linking
  • Chapter 2: C++ Basics Improvement
    • Default Parameters
    • Inline Function
    • Function Overloading
    • new and delete
    • const and Pointers
    • References in Detail
  • Chapter 3: Object-Oriented Principles
  • Class and Object
  • Constructor and Destructor
  • Shallow Copy and Deep Copy
  • Initializer List
  • Various Member Functions
  • Pointer to Class Members
  • Chapter 4: Template Programming
  • Function Templates
  • Class Templates
  • Memory Allocators
  • Chapter 5: Operator Overloading
    • Operator Overloading
    • Introduction to Iterators
    • Issues of Iterator Invalidation
    • More about new and delete
    • Overloading of new and delete: Object Pool
  • Chapter 6: Inheritance and Polymorphism
    • Look inside Inheritance
    • More about Inheritance
    • Virtual Functions, Static Binding and Dynamic Binding
    • More about Virtual Functions
    • Understanding Polymorphism
    • Abstract Classes
    • Frequently Asked Interview Questions: Polymorphism
  • Chapter 7: Multiple Inheritance
    • Virtual Inheritance and Virtual Base Classes
    • Diamond Problem
    • Four Kinds of Type Conversions
  • Chapter 8: Standard Template Library
    • Sequence Containers
    • Container Adaptors
    • Associative Containers
    • More about Iterators
    • Function Objects
    • Generic Algorithms, Binders and Lambda Expressions
  • Chapter 9: Object Optimization
    • Behind the Object
    • Optimizing Objects in Functions
    • Member Functions with Rvalue References
    • Move Semantics and Perfect Forwarding
  • Chapter 10: Smart Pointers
    • Smart Pointers
    • Smart Pointers without Reference Counting
    • Smart Pointers with Reference Counting
    • Custom Deleters
  • Chapter 11: Function Objects and Binders
    • More about Binders
    • Introduction to std::function
    • Template Specialization and Argument Deduction
    • More about std::function
    • std::bind(): A Simple Thread Pool
    • More about Lambda Expressions
  • Chapter 12: Multithreading
    • Important Features in C++11
    • Multithreaded Programming with std::thread
    • Mutual Exclusion
    • Producer-Consumer Problem
    • Atomic Operations
    • Thread Visibility and volatile
  • Chapter 13: Design Patterns
    • Singleton Pattern
    • Factory Pattern
    • Proxy Pattern
    • Decorator Pattern
    • Adapter Pattern
    • Observer Pattern
Powered by GitBook
On this page

Was this helpful?

  1. Chapter 8: Standard Template Library

Function Objects

A Function Object is simply any object that can be called as if it is a function. Remember in C, we can use function pointers like this:

int sum(int a, int b) {
    return a + b;
}
​
int main() {
    int ret = sum(10, 20);
    return 0;
}

In C++, a function object is any object for which the function call operator () is defined. We can call functions from the object:

class Sum {
public:
    int operator()(int a, int b) {
        return a + b;
    }
};
int main() {
    Sum sum;
    int ret = sum(10, 20);
}

What's the benefit of using function objects? Let's look at the following example, where we defined a template function compare() for comparing two elements.

template<typemane T>
bool compare(T a, T b) {
    return a < b;
}
int main() {
    cout << compare(10, 20) << endl;    // 0
    cout << compare('b', 'y') << endl;  // 1
    return 0;
}

Here we compare the elements using operator <. What if we want to use > instead? We need to define another comparing function and provide a unified interface. A solution using function pointers in C style looks like this:

template<typename T>
bool greater(T a, T b) {
    return a > b;
}
template<typename T>
bool less(T a, T b) {
    return a < b;
}
template<typename T, typename Compare>
bool compare(T a, T b, Compare comp) {
    return comp(a, b);
}
int main() {
    cout << compare(10, 20, greater<int>) << endl;  // 0
    cout << compare('b', 'y', less<int>) << endl;   // 1
    return 0;
}

Here we use function pointers as parameter and call the corresponding function through a function pointer. But remember that template functions are expanded at their call points, which means that greater() or less() can not be inlined inside compare(). This reduces efficiency since there is function call overhead.

A better approach is to use function objects:

template<typename T>
class greater {
public:
    bool operator()(T a, T b) {
        return a > b;
    }  
};
template<typename T>
class less {
public:
    bool operator()(T a, T b) {
        return a < b;
    }  
};
template<typename T, typename Compare>
bool compare(T a, T b, Compare comp) {
    return comp(a, b);
}
int main() {
    cout << compare(10, 20, greater<int>()) << endl;    // 0
    cout << compare('b', 'y', less<int>()) << endl; // 1
    return 0;
}

Now inside compare(), we simply call the member function operator () through objects. In this way, the function call overhead can be omitted, thus improving efficiency.

Moreover, since function objects are created from classes, we can add member variables to record other information used when a function object is used, for example the total number of calls. This greatly improves programming flexibility.

Function objects are widely used in STL containers and generic algorithms. For example, we can use function objects greater or less to change the underlying algorithms of containers:

priority_queue<int, vector<int>, greater<int>> pq;
set<int, greater<int>> s;
PreviousMore about IteratorsNextGeneric Algorithms, Binders and Lambda Expressions

Last updated 4 years ago

Was this helpful?