Click here to Skip to main content
15,889,992 members
Articles / Programming Languages / C++11
Tip/Trick

std::function: template based function pointer /object

Rate me:
Please Sign up or sign in to vote.
4.67/5 (2 votes)
3 Jun 2013CPOL3 min read 28K   5  
This tip will demonstrate std::function in various avatars, with function pointers and std::bind.

Introduction

std::function is defined in the functional header, it is a polymorphic class template wrapper. It can store any callable target. We can consider it to be a super set of a function pointer as it can store objects too.

Using std::function we can create our new functional signature using std::bind.

Let us go straight for the std::function declaration.

C++
std::function< FunctionSignature > FunctionObject = FunctionReference;

Here,

  • FunctionSignature is the signature of the function we are binding to.
  • FunctionObject is an object of the template we have defined.
  • FunctionReference is the reference of the function we want to create.

Using the code

For this tip, I have created two functions which I am going to use throughout the tip:

C++
void WriteToConsoleScreen(std::wstring szMyName)
{
    wprintf(_T("my name is %s \n"),szMyName.c_str());
}

void WriteToConsoleScreenWithAge(std::wstring szMyName,int age)
{
    wprintf(_T("my name is %s and age equal to %d\n"),szMyName.c_str(),age);
}

Example # 1: Storing normal functions

C++
//using Function Template
std::function<void(std::wstring)> fnwriteToConsoleScreen = WriteToConsoleScreen;
fnwriteToConsoleScreen(_T("VisualCPP"));

Similarly in a function pointer, we have to use this code…

C++
//Using Function Pointer
typedef void (*MySingleArgFunction) (std::wstring);
//assign memory to out 
MySingleArgFunction fnwriteToConsoleScreen1 = WriteToConsoleScreen;
fnwriteToConsoleScreen1(_T("VisualCPP"));

Example # 2: Storing using function lambdas

We can use the C++11 feature lambdas in std::function, which is a little typical in a function pointer, and having an object pointing to an anonymous function we can use it again and again.

C++
// std::Function with Lambdas One Argument
std::function<void(std::wstring)> fnwriteToConsoleScreen = [](std::wstring szMyName){
wprintf(_T("my name is %s \n"),szMyName.c_str());
};

fnwriteToConsoleScreen(_T("VisualCPP"));

In the below example, I am passing the parent variable in our lambda function:

C++
// std::Function with Lambdas One Argument, and passing parent scope variable
int age =30;
std::function<void(std::wstring)> fnwriteToConsoleScreen2 = [age](std::wstring szMyName){
    wprintf(_T("my name is %s and age is %d \n"),szMyName.c_str(),age);
    };

fnwriteToConsoleScreen2(_T("VisualCPP"));

I am using the auto keyword to create a named object for the anonymous method, it creates a variable almost equivalent to the function pointer.

C++
//using  auto keyword, which will create  anonymous function object, to be used again and again
auto fnwriteToConsoleScreen3 = [](std::wstring szMyName){
		wprintf(_T("my name is %s \n"),szMyName.c_str());
	};
fnwriteToConsoleScreen3(_T("VisualCPP"));

Example # 3: Storing using std::bind

std::bind helps you bind a variable to a function. It comes very handy when you want to have your own function signature instead of a defined function. It provides functionality like an optional parameter. In the first example, I bind the constant value using std::bind, you can see now that my function object calling signature has been changed from void(std::wstring) to void() as I have already bound my argument value at runtime.

C++
// using std::bind, which is useful creating with predefined argument....
std::function<void()> fnwriteToConsoleScreen_staticarg = std::bind(WriteToConsoleScreen, _T("VisualCPP"));

fnwriteToConsoleScreen_staticarg();

Similar to the previous one, however I have bound the variable instead of the constant value.

C++
// using std::bind, which is useful creating with predefined argument.... with dynamic argument
std::wstring strDynamicArg = _T("VisualCPPDynamic");

std::function<void()> fnwriteToConsoleScreen_dynamicarg = std::bind(WriteToConsoleScreen, strDynamicArg);
fnwriteToConsoleScreen_dynamicarg();

As mentioned in the start of the example, we can declare placeholders, which work like optional parameters; however it’s not restricted to the right side. For using a placeholder, we have to use its namespace std::placeholders, which provides the declaration for _1, _2, _3, etc. It would be useful in a condition when you have to call a function whose one argument is constant throughout the programming scope and another argument keeps changing based on some condition and you have no authority over the base function. Now let us see a case for WriteToConsoleScreenWithAge, where I want my string argument to be constant and age to be different. In traditional programming we will pass string and int arguments every-time we call the function, however using std::bind we can create a functional template where we specify the string argument and keep place of the placeholder age.

C++
using namespace std::placeholders;
// using std::bind, with PlaceHolder
auto fnwriteToConsoleScreen_PlaceHolderarg = std::bind(WriteToConsoleScreenWithAge,  _T("VisualCPP"),_1);

fnwriteToConsoleScreen_PlaceHolderarg(30);

Above _1 is placeholder for age, which could be specified every time we call the function object.

Example # 4: Using class function and functor

For this example I have defined a class like this:

C++
class ConsoleFunctor
{
public:
    ConsoleFunctor()
    {
    }
    void operator()(std::wstring szMyName)
    {
        wprintf(_T("my name is %s \n"),szMyName.c_str());
    };

    void WriteToConsoleWithAge(std::wstring szMyName,int age)
    {
        wprintf(_T("my name is %s and age equal to %d\n"),szMyName.c_str(),age);
    }
};

We can create a function object for a functor like this:

C++
ConsoleFunctor functObject;
std::function<void(std::wstring)> fnWriteToConsole(functObject);
fnWriteToConsole(_T("VisualCPP with existingObject"));

First we create an object of the function and then pass that object to a functional template and call functionObject normally to invoke functor. And for calling the class function using the functional template, we can use the following code:

C++
std::function<void(const ConsoleFunctor,std::wstring,int)> 
       fnWriteToConsole1 = &ConsoleFunctor::WriteToConsoleWithAge;
fnWriteToConsole1(functObject,_T("VisualCPP with existingObject"),30);

Points of Interest

std::function is the interesting piece of code, it could come handy in various conditions. Hope we hear more development about this in future.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
He used to have biography here Smile | :) , but now he will hire someone (for free offcourse Big Grin | :-D ), Who writes his biography on his behalf Smile | :)

He is Great Fan of Mr. Johan Rosengren (his idol),Lim Bio Liong, Nishant S and DavidCrow and Believes that, he will EXCEL in his life by following there steps!!!

He started with Visual C++ then moved to C# then he become language agnostic, you give him task,tell him the language or platform, he we start immediately, if he knows the language otherwise he quickly learn it and start contributing productively

Last but not the least, For good 8 years he was Visual CPP MSMVP!

Comments and Discussions

 
-- There are no messages in this forum --