Lei Mao bio photo

Lei Mao

Machine Learning, Artificial Intelligence, Computer Science.

Twitter Facebook LinkedIn GitHub   G. Scholar E-Mail RSS

Introduction

C++ function template uses rvalue reference for different function expression arguments in the higher-order function. Because it is compiled time polymorphism, the code could be optimized very well and the performance should be very good.


In this blog post, I would like to show how to use the C++ function template.

Examples

/* 
 * function_template.cpp
 */
#include <iostream>

template <typename T, typename TF>
T runBinaryFunction(T x, T y, TF&& f)
{
    return f(x, y);
}

template <typename T>
T add(T x, T y)
{
    return x + y;
}

template <class T>
class Add
{
public:
    T operator() (T x, T y) const 
    {
        return x + y;
    }
};

template <class T>
class Calculator
{
public:
    static T add(T x, T y)
    {
        return x + y;
    }
};

template <class T>
class Calculator2
{
public:
    T add(T x, T y)
    {
        return x + y;
    }
};

int main()
{
    int x = 1;
    int y = 2;

    // Functions
    std::cout << &add<int> << std::endl; // add<int> is an lvalue expression
    // Without using std::move, std::move will be implicitly added for rvalue arguments.
    std::cout << runBinaryFunction(x, y, std::move(add<int>)) << std::endl;
    // Functors
    // std::cout << &Add<int>() << std::endl; // Error: Add<int>() is an rvalue expression
    std::cout << runBinaryFunction(x, y, Add<int>()) << std::endl;
    // Lambda expressions
    // std::cout << &([](int x,int y)->int{return x + y;}) << std::endl; // Error: [](int x,int y)->int{return x + y;} is an rvalue expression
    std::cout << runBinaryFunction(x, y, [](int x,int y)->int{return x + y;}) << std::endl;
    // Static methods
    std::cout << &Calculator<int>::add << std::endl; // Calculator<int>::add is an lvalue expression
    // Without using std::move, std::move will be implicitly added for rvalue arguments.
    std::cout << runBinaryFunction(x, y, std::move(Calculator<int>::add)) << std::endl;
    // Non-static methods - failed
    /*
    Calculator2<int> calculator;
    std::cout << runBinaryFunction(x, y, calculator.add) << std::endl;
    */
}

To compile the program, please run the following command in the terminal.

$ g++ function_template.cpp -o function_template --std=c++11

Using TF f would actually also work, but it would not serve as a reference. It copies the rvalues to f, which is unnecessary.

Conclusions

The application of the function template might not be as generic as std::function, but its performance should be better.