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 compile 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 reference. It copies the rvalues to f, which is unnecessary.

Conclusions

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