#include "boost/function.hpp"
The point of this post is showing how using std::function we can do all what we can do using function pointers, but the viceversa is not true. For instance, std::function could accept functor as argument.
Let's say we want to develop a class, Notifier, to call back the functions we register on it any time its state change.
A first implementation uses a vector of function pointers. And it works fine.
The problem is if we want to use functors, too. The reason is quite clear, a functor gives us more power, since it could keeps its own internal status.
But that requires we redesign our class, using std::function instead. We call it NotifierExt. We see that the change in the code is minimal, and the advantage is self evident, I think.
Here is the code:
#include <iostream>
#include <vector>
#include <functional>
namespace
{
void printNewValue(int i)
{
std::cout << "The value has been updated and is now " << i << std::endl;
}
void changeObserver(int i)
{
std::cout << "Ah, the value has changed!" << std::endl;
}
class PrintPreviousValue
{
int lastValue_;
public:
PrintPreviousValue() : lastValue_(-1) {}
void operator()(int i)
{
std::cout << "Previous value was " << lastValue_ << std::endl;
lastValue_ = i;
}
};
class Notifier
{
typedef void (*FunType)(int);
std::vector<FunType> vec_;
int value_;
public:
void addObserver(FunType t)
{
vec_.push_back(t);
}
void changeValue(int i)
{
value_ = i;
for(size_t i=0; i < vec_.size(); ++i)
vec_[i](value_);
}
};
class NotifierExt
{
typedef std::function<void(int)> FunType;
std::vector<FunType> vec_;
int value_;
public:
void addObserver(FunType t)
{
vec_.push_back(t);
}
void changeValue(int i)
{
value_ = i;
for(size_t i = 0; i < vec_.size(); ++i)
vec_[i](value_);
}
};
}
void function02()
{
std::cout << "Using function pointer" << std::endl;
Notifier n;
n.addObserver(&printNewValue);
n.addObserver(&changeObserver);
n.changeValue(42);
std::cout << "Using std::function" << std::endl;
NotifierExt ne;
ne.addObserver(&printNewValue);
ne.addObserver(&changeObserver);
ne.addObserver(PrintPreviousValue());
ne.changeValue(42);
ne.changeValue(39);
}
The code is based on an example provided by "Beyond the C++ Standard Library: An Introduction to Boost", by Björn Karlsson, an Addison Wesley Professional book. An interesting reading indeed.
No comments:
Post a Comment