Related
I want to store a pointer to member function in some kind of object. Later in the programm i want to compare it to another one.
Requirenment is that the type of object that holds first pointer must be concrete (i need to store them in one container)
I failed to apply Type-erasure here because template functions can not be virtual, so i can not provide an interface "compareWith" to be overridden.
There is a half-working solution i came up with, but the problem here is with the types of Fnc objects - those are different and can not be stored in the same container. I do need to store them in the same container.
Simplified version is below:
template<class T>
class Fnc
{
public:
Fnc(T&& fnc) : m_fnc(std::forward<T>(fnc)) {}
template<class Y>
bool compareWith(const Fnc<Y>& other) {
return other.m_fnc == m_fnc;
}
private:
T m_fnc;
};
class MyClass
{
public:
void method1(int a);
void method2(int a);
void method3();
}
int main() {
//This block obviously works because i didnt try to put Fnc-objects to container
Fnc fnc1(&MyClass::method1);
Fnc fnc2(&MyClass::method2);
printf("%d\n", fnc1.compareWith(Fnc(&MyClass::method1))); //prints "1"
printf("%d\n", fnc1.compareWith(Fnc(&MyClass::method3))); //prints "0"
printf("%d\n", fnc2.compareWith(Fnc(&MyClass::method2))); //prints "1"
//This block is not working because Fnc is not polymorphic(and cannot be - template functions can not be virtual)
std::vecotor<Fnc> methods;
methods.push_back(Fnc(&MyClass::method1));
methods.push_back(Fnc(&MyClass::method2));
methods.push_back(Fnc(&MyClass::method3));
printf("%d\n", methods[0].compareWith(Fnc(&MyClass::method1))); //should be "1"
printf("%d\n", methods[1].compareWith(Fnc(&MyClass::method2))); //should be "1"
printf("%d\n", methods[2].compareWith(Fnc(&MyClass::method3))); //should be "1"
printf("%d\n", methods[0].compareWith(Fnc(&MyClass::method2))); //should be "0"
}
With a hint given by #joergbrech i made up some kind of hash that easily distinguishes one pointer to member function from another. And it works with overloads too.
The solution is very simple, yet may not be very robust. But it works nicely for me. The benefit is that it works with C++11 and doesnt require any fancy stuff :)
Working example:
//WARINING: sizeof(pointer-to-member-function) may not always be <= 8
//Consider changing the hash to be an array!
//I write it as uint64_t for the sake of ease.
template<typename R, class Class, class... Args>
uint64_t getId(R(Class::*ptr)(Args...)) {
uint64_t id = 0;
memcpy(&id, &ptr, sizeof(ptr));
return id;
}
class MyClass
{
public:
void test(int a) {
}
void test(double a) {
}
void test2(int a) {
}
};
int main() {
//Now every pointer-to-member-function may be simply represented by a number
//and compared at any time.
//static_cast is needed for functions that are overloaded if you wonder.
cout << getId(static_cast<void(MyClass::*)(int)>(&MyClass::test))
<< getId(static_cast<void(MyClass::*)(double)>(&MyClass::test))
<< getId(static_cast<void(MyClass::*)(double)>(&MyClass::test))
<< getId(&MyClass::test2);
//Output was: 4389464 4389304 4389304 4389616
// ^ != ^ == ^ != ^
return 0;
}
I'm working with a C++ project and I need to do some assignment code to assign one object to another with a different type like this:
MyClass1 o1;
MyClass2 o2;
o2 = o1;
Ofc, we can make this work with the help of a copy assignment operator of MyClass2: MyClass2& operator=(const MyClass1&).
But this gonna be a very heavy job for me because there has been thousands of classes, which need to do the assignment like o2 = o1. I don't want to add a copy assignment operator for each of them one by one...
I'm thinking if there is some other way, such as some TMP method to help me...
I can ensure that MyClass1 and MyClass2 have exactly the same data members with the same declaration order (see below). If so, is there some TMP method, which could help me?
struct MyClass1 {
int a;
char ch;
std::string msg;
// some virtual member functions
};
struct MyClass2 {
int a;
char ch;
std::string msg;
// some virtual member functions
};
BTW, you may want to ask why there are such two classes/structs with the same data members. Well, this is about some historical reason, I can't fusion them onto one class/struct.
UPDATE
It seems that I didn't make my question clear. I'll make an example here.
void doJob(const MyClass1& o1) {}
void func1(MyClass1 o1) {
doJob(o1);
}
void func2(MyClass2 o2) {
MyClass o1;
o1.? = o2.?; // assign each element of o2 to o1.
doJob(o1);
}
Here is the real case. As you see, o1.? = o2.? contains multi lines, it depends on how many data members of MyClass1/MyClass2. I'm trying to find some way to avoid this stupid assignment of all data members one by one in the func2.
Also, as I said, I have thousands of classes like MyClass1/MyClass2, meaning that these classes have totally different data members.
So for MyClass1 and MyClass2, o1.? = o2.? is o1.a = o2.a; o1.ch = o2.ch; o1.msg = o2.msg; But for other classes, it may become o1.f = o2.f; o1.vec = o2.vec;. That's why I'm thinking I may need some TMP technique...
UPDATE2
Alice developed the classes:
struct MyClass1 {// data members};
struct MyClass2 {// data members};
// MyClass1 and MyClass2 have exactly the same data members and declaration order
struct MyClass3 {// data members};
struct MyClass4 {// data members};
// MyClass3 and MyClass4 have exactly the same data members and declaration order
...
...
struct MyClass1000 {// data members};
struct MyClass1001 {// data members};
// MyClass1000 and MyClass1001 have exactly the same data members and declaration order
I'm developing the functions:
void doJob1(const MyClass1& o1) {}
void func1(MyClass1 o1) {
doJob(o1);
}
void func2(MyClass2 o2) {
MyClass1 o1;
o1.? = o2.?; // assign each element of o2 to o1.
doJob1(o1);
}
...
...
void doJob1000(const MyClass1000& o1) {}
void func1000(MyClass1000 o1) {
doJob1000(o1);
}
void func1001(MyClass1001 o2) {
MyClass1000 o1;
o1.? = o2.?; // assign each element of o2 to o1.
doJob1000(o1);
}
Why did Alice do such a stupid design? For some historical reason...
Why not using std::memcpy? Because these classes contain virtual functions.
yes, you can... but I is not recommended unless the two classes have an exact one to one correspondence and the exact same meaning in the domain of your problem.
Why is not recommended?
Because the operation needs to be manually implemented (the compiler cannot help with a = default declaration).
auto operator=(MyClass1 const& other) -> MyClass2& {
std::tie(a, ch, msg) = std::tie(other.a, other.ch, other.msg);
return *this;
}
Because if you defined assignment, you will eventually need to define equality (==), and inequality (!=) and in both directions. Otherwise the clases will not behave logically.
bool operator==(MyClass1 const& mc1, MyClass2 const& mc2) {
return std::tie(mc1.a, mc1.ch, mc1.msg) == std::tie(mc2.a, mc2.ch, mc2.msg);
}
bool operator==(MyClass2 const& mc2, MyClass1 const& mc1) {
return std::tie(mc1.a, mc1.ch, mc1.msg) == std::tie(mc2.a, mc2.ch, mc2.msg);
}
bool operator!=(MyClass1 const& mc1, MyClass2 const& mc2) {
return std::tie(mc1.a, mc1.ch, mc1.msg) != std::tie(mc2.a, mc2.ch, mc2.msg);
}
bool operator!=(MyClass2 const& mc2, MyClass1 const& mc1) {
return std::tie(mc1.a, mc1.ch, mc1.msg) != std::tie(mc2.a, mc2.ch, mc2.msg);
}
Because if you define assignment, you will to define a constructor or a conversion from one to the other.
/*explicit?*/ operator MyClass1() const& {return {a, ch, msg};} // need thios
and a move constructor?
/*explicit?*/ operator MyClass1() && {return {a, ch, std::move(msg)};} // need this
if one can be ordered the other also, and you will need to define order between the two classes, in both directions
// won't even try
// bool operator<
// bool operator<=
// bool operator>
// bool operator>=
// bool operator<
// bool operator<=
// bool operator>
// bool operator>=
and for that matter any function that work with one should work with the other, because well, when you assign you are saying that two things are logical equal among other tings.
full code here: https://godbolt.org/z/c8d34eT48
While it seems to be your case (albeit a very suspicious case), as you see, you open a Pandora's box by defining equality between two classes.
Just by calling the "assignment" convert instead you save your self a big headache. Don't use operator=. My recommended code is to just use another name:
MyClass2& convert(MyClass1 const& from, MyClass2& to) {
std::tie(to.a, to.ch, to.msg) = std::tie(from.a, from.ch, from.msg);
return to;
}
MyClass2& convert(MyClass1&& from, MyClass2& to) {
std::tie(to.a, to.ch, to.msg) = std::tie(from.a, from.ch, std::move(from.msg));
return to;
}
More material: https://www.youtube.com/watch?v=ABkxMSbejZI
Once you understand the drawbacks, std::tie can help you (as shown).
Also, if all classes are public and simple, Boost.PFR https://www.boost.org/doc/libs/1_78_0/doc/html/boost_pfr.html
struct iClass
{
int a;
char ch;
std::string msg;
// implement iClass == = operator
};
struct MyClass1 : virtual iClass{
// some virtual member functions
};
struct MyClass2 : virtual iClass {
// some virtual member functions
};
Should be able to compare by reintrepret_cast to iClass as well assignment.
I keep hearing a lot about functors in C++. Can someone give me an overview as to what they are and in what cases they would be useful?
A functor is pretty much just a class which defines the operator(). That lets you create objects which "look like" a function:
// this is a functor
struct add_x {
add_x(int val) : x(val) {} // Constructor
int operator()(int y) const { return x + y; }
private:
int x;
};
// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument
std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
assert(out[i] == in[i] + 1); // for all i
There are a couple of nice things about functors. One is that unlike regular functions, they can contain state. The above example creates a function which adds 42 to whatever you give it. But that value 42 is not hardcoded, it was specified as a constructor argument when we created our functor instance. I could create another adder, which added 27, just by calling the constructor with a different value. This makes them nicely customizable.
As the last lines show, you often pass functors as arguments to other functions such as std::transform or the other standard library algorithms. You could do the same with a regular function pointer except, as I said above, functors can be "customized" because they contain state, making them more flexible (If I wanted to use a function pointer, I'd have to write a function which added exactly 1 to its argument. The functor is general, and adds whatever you initialized it with), and they are also potentially more efficient. In the above example, the compiler knows exactly which function std::transform should call. It should call add_x::operator(). That means it can inline that function call. And that makes it just as efficient as if I had manually called the function on each value of the vector.
If I had passed a function pointer instead, the compiler couldn't immediately see which function it points to, so unless it performs some fairly complex global optimizations, it'd have to dereference the pointer at runtime, and then make the call.
Little addition. You can use boost::function, to create functors from functions and methods, like this:
class Foo
{
public:
void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"
and you can use boost::bind to add state to this functor
boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"
and most useful, with boost::bind and boost::function you can create functor from class method, actually this is a delegate:
class SomeClass
{
std::string state_;
public:
SomeClass(const char* s) : state_(s) {}
void method( std::string param )
{
std::cout << state_ << param << std::endl;
}
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"
You can create list or vector of functors
std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
events.begin(), events.end(),
boost::bind( boost::apply<void>(), _1, e));
There is one problem with all this stuff, compiler error messages is not human readable :)
A Functor is a object which acts like a function.
Basically, a class which defines operator().
class MyFunctor
{
public:
int operator()(int x) { return x * 2;}
}
MyFunctor doubler;
int x = doubler(5);
The real advantage is that a functor can hold state.
class Matcher
{
int target;
public:
Matcher(int m) : target(m) {}
bool operator()(int x) { return x == target;}
}
Matcher Is5(5);
if (Is5(n)) // same as if (n == 5)
{ ....}
Name "functor" has been traditionaly used in category theory long before C++ appeared on the scene. This has nothing to do with C++ concept of functor. It's better to use name function object instead of what we call "functor" in C++. This is how other programming languages call similar constructs.
Used instead of plain function:
Features:
Function object may have state
Function object fits into OOP (it behaves like every other object).
Cons:
Brings more complexity to the program.
Used instead of function pointer:
Features:
Function object often may be inlined
Cons:
Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
Used instead of virtual function:
Features:
Function object (non-virtual) doesn't require vtable and runtime dispatching, thus it is more efficient in most cases
Cons:
Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
Like others have mentioned, a functor is an object that acts like a function, i.e. it overloads the function call operator.
Functors are commonly used in STL algorithms. They are useful because they can hold state before and between function calls, like a closure in functional languages. For example, you could define a MultiplyBy functor that multiplies its argument by a specified amount:
class MultiplyBy {
private:
int factor;
public:
MultiplyBy(int x) : factor(x) {
}
int operator () (int other) const {
return factor * other;
}
};
Then you could pass a MultiplyBy object to an algorithm like std::transform:
int array[5] = {1, 2, 3, 4, 5};
std::transform(array, array + 5, array, MultiplyBy(3));
// Now, array is {3, 6, 9, 12, 15}
Another advantage of a functor over a pointer to a function is that the call can be inlined in more cases. If you passed a function pointer to transform, unless that call got inlined and the compiler knows that you always pass the same function to it, it can't inline the call through the pointer.
For the newbies like me among us: after a little research I figured out what the code jalf posted did.
A functor is a class or struct object which can be "called" like a function. This is made possible by overloading the () operator. The () operator (not sure what its called) can take any number of arguments. Other operators only take two i.e. the + operator can only take two values (one on each side of the operator) and return whatever value you have overloaded it for. You can fit any number of arguments inside a () operator which is what gives it its flexibility.
To create a functor first you create your class. Then you create a constructor to the class with a parameter of your choice of type and name. This is followed in the same statement by an initializer list (which uses a single colon operator, something I was also new to) which constructs the class member objects with the previously declared parameter to the constructor. Then the () operator is overloaded. Finally you declare the private objects of the class or struct you have created.
My code (I found jalf's variable names confusing)
class myFunctor
{
public:
/* myFunctor is the constructor. parameterVar is the parameter passed to
the constructor. : is the initializer list operator. myObject is the
private member object of the myFunctor class. parameterVar is passed
to the () operator which takes it and adds it to myObject in the
overloaded () operator function. */
myFunctor (int parameterVar) : myObject( parameterVar ) {}
/* the "operator" word is a keyword which indicates this function is an
overloaded operator function. The () following this just tells the
compiler that () is the operator being overloaded. Following that is
the parameter for the overloaded operator. This parameter is actually
the argument "parameterVar" passed by the constructor we just wrote.
The last part of this statement is the overloaded operators body
which adds the parameter passed to the member object. */
int operator() (int myArgument) { return myObject + myArgument; }
private:
int myObject; //Our private member object.
};
If any of this is inaccurate or just plain wrong feel free to correct me!
A functor is a higher-order function that applies a function to the parametrized(ie templated) types. It is a generalization of the map higher-order function. For example, we could define a functor for std::vector like this:
template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::vector<U> fmap(F f, const std::vector<T>& vec)
{
std::vector<U> result;
std::transform(vec.begin(), vec.end(), std::back_inserter(result), f);
return result;
}
This function takes a std::vector<T> and returns std::vector<U> when given a function F that takes a T and returns a U. A functor doesn't have to be defined over container types, it can be defined for any templated type as well, including std::shared_ptr:
template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::shared_ptr<U> fmap(F f, const std::shared_ptr<T>& p)
{
if (p == nullptr) return nullptr;
else return std::shared_ptr<U>(new U(f(*p)));
}
Heres a simple example that converts the type to a double:
double to_double(int x)
{
return x;
}
std::shared_ptr<int> i(new int(3));
std::shared_ptr<double> d = fmap(to_double, i);
std::vector<int> is = { 1, 2, 3 };
std::vector<double> ds = fmap(to_double, is);
There are two laws that functors should follow. The first is the identity law, which states that if the functor is given an identity function, it should be the same as applying the identity function to the type, that is fmap(identity, x) should be the same as identity(x):
struct identity_f
{
template<class T>
T operator()(T x) const
{
return x;
}
};
identity_f identity = {};
std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<int> is1 = fmap(identity, is);
std::vector<int> is2 = identity(is);
The next law is the composition law, which states that if the functor is given a composition of two functions, it should be the same as applying the functor for the first function and then again for the second function. So, fmap(std::bind(f, std::bind(g, _1)), x) should be the same as fmap(f, fmap(g, x)):
double to_double(int x)
{
return x;
}
struct foo
{
double x;
};
foo to_foo(double x)
{
foo r;
r.x = x;
return r;
}
std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<foo> is1 = fmap(std::bind(to_foo, std::bind(to_double, _1)), is);
std::vector<foo> is2 = fmap(to_foo, fmap(to_double, is));
Here's an actual situation where I was forced to use a Functor to solve my problem:
I have a set of functions (say, 20 of them), and they are all identical, except each calls a different specific function in 3 specific spots.
This is incredible waste, and code duplication. Normally I would just pass in a function pointer, and just call that in the 3 spots. (So the code only needs to appear once, instead of twenty times.)
But then I realized, in each case, the specific function required a completely different parameter profile! Sometimes 2 parameters, sometimes 5 parameters, etc.
Another solution would be to have a base class, where the specific function is an overridden method in a derived class. But do I really want to build all of this INHERITANCE, just so I can pass a function pointer????
SOLUTION: So what I did was, I made a wrapper class (a "Functor") which is able to call any of the functions I needed called. I set it up in advance (with its parameters, etc) and then I pass it in instead of a function pointer. Now the called code can trigger the Functor, without knowing what is happening on the inside. It can even call it multiple times (I needed it to call 3 times.)
That's it -- a practical example where a Functor turned out to be the obvious and easy solution, which allowed me to reduce code duplication from 20 functions to 1.
Like has been repeated, functors are classes that can be treated as functions (overload operator ()).
They are most useful for situations in which you need to associate some data with repeated or delayed calls to a function.
For example, a linked-list of functors could be used to implement a basic low-overhead synchronous coroutine system, a task dispatcher, or interruptable file parsing.
Examples:
/* prints "this is a very simple and poorly used task queue" */
class Functor
{
public:
std::string output;
Functor(const std::string& out): output(out){}
operator()() const
{
std::cout << output << " ";
}
};
int main(int argc, char **argv)
{
std::list<Functor> taskQueue;
taskQueue.push_back(Functor("this"));
taskQueue.push_back(Functor("is a"));
taskQueue.push_back(Functor("very simple"));
taskQueue.push_back(Functor("and poorly used"));
taskQueue.push_back(Functor("task queue"));
for(std::list<Functor>::iterator it = taskQueue.begin();
it != taskQueue.end(); ++it)
{
*it();
}
return 0;
}
/* prints the value stored in "i", then asks you if you want to increment it */
int i;
bool should_increment;
int doSomeWork()
{
std::cout << "i = " << i << std::endl;
std::cout << "increment? (enter the number 1 to increment, 0 otherwise" << std::endl;
std::cin >> should_increment;
return 2;
}
void doSensitiveWork()
{
++i;
should_increment = false;
}
class BaseCoroutine
{
public:
BaseCoroutine(int stat): status(stat), waiting(false){}
void operator()(){ status = perform(); }
int getStatus() const { return status; }
protected:
int status;
bool waiting;
virtual int perform() = 0;
bool await_status(BaseCoroutine& other, int stat, int change)
{
if(!waiting)
{
waiting = true;
}
if(other.getStatus() == stat)
{
status = change;
waiting = false;
}
return !waiting;
}
}
class MyCoroutine1: public BaseCoroutine
{
public:
MyCoroutine1(BaseCoroutine& other): BaseCoroutine(1), partner(other){}
protected:
BaseCoroutine& partner;
virtual int perform()
{
if(getStatus() == 1)
return doSomeWork();
if(getStatus() == 2)
{
if(await_status(partner, 1))
return 1;
else if(i == 100)
return 0;
else
return 2;
}
}
};
class MyCoroutine2: public BaseCoroutine
{
public:
MyCoroutine2(bool& work_signal): BaseCoroutine(1), ready(work_signal) {}
protected:
bool& work_signal;
virtual int perform()
{
if(i == 100)
return 0;
if(work_signal)
{
doSensitiveWork();
return 2;
}
return 1;
}
};
int main()
{
std::list<BaseCoroutine* > coroutineList;
MyCoroutine2 *incrementer = new MyCoroutine2(should_increment);
MyCoroutine1 *printer = new MyCoroutine1(incrementer);
while(coroutineList.size())
{
for(std::list<BaseCoroutine *>::iterator it = coroutineList.begin();
it != coroutineList.end(); ++it)
{
*it();
if(*it.getStatus() == 0)
{
coroutineList.erase(it);
}
}
}
delete printer;
delete incrementer;
return 0;
}
Of course, these examples aren't that useful in themselves. They only show how functors can be useful, the functors themselves are very basic and inflexible and this makes them less useful than, for example, what boost provides.
Functors are used in gtkmm to connect some GUI button to an actual C++ function or method.
If you use the pthread library to make your app multithreaded, Functors can help you.
To start a thread, one of the arguments of the pthread_create(..) is the function pointer to be executed on his own thread.
But there's one inconvenience. This pointer can't be a pointer to a method, unless it's a static method, or unless you specify it's class, like class::method. And another thing, the interface of your method can only be:
void* method(void* something)
So you can't run (in a simple obvious way), methods from your class in a thread without doing something extra.
A very good way of dealing with threads in C++, is creating your own Thread class. If you wanted to run methods from MyClass class, what I did was, transform those methods into Functor derived classes.
Also, the Thread class has this method:
static void* startThread(void* arg)
A pointer to this method will be used as an argument to call pthread_create(..). And what startThread(..) should receive in arg is a void* casted reference to an instance in heap of any Functor derived class, which will be casted back to Functor* when executed, and then called it's run() method.
Except for used in callback, C++ functors can also help to provide a Matlab liking access style to a matrix class. There is a example.
A big advantage of implementing functions as functors is that they can maintain and reuse state between calls. For example, many dynamic programming algorithms, like the Wagner-Fischer algorithm for calculating the Levenshtein distance between strings, work by filling in a large table of results. It's very inefficient to allocate this table every time the function is called, so implementing the function as a functor and making the table a member variable can greatly improve performance.
Below is an example of implementing the Wagner-Fischer algorithm as a functor. Notice how the table is allocated in the constructor, and then reused in operator(), with resizing as necessary.
#include <string>
#include <vector>
#include <algorithm>
template <typename T>
T min3(const T& a, const T& b, const T& c)
{
return std::min(std::min(a, b), c);
}
class levenshtein_distance
{
mutable std::vector<std::vector<unsigned int> > matrix_;
public:
explicit levenshtein_distance(size_t initial_size = 8)
: matrix_(initial_size, std::vector<unsigned int>(initial_size))
{
}
unsigned int operator()(const std::string& s, const std::string& t) const
{
const size_t m = s.size();
const size_t n = t.size();
// The distance between a string and the empty string is the string's length
if (m == 0) {
return n;
}
if (n == 0) {
return m;
}
// Size the matrix as necessary
if (matrix_.size() < m + 1) {
matrix_.resize(m + 1, matrix_[0]);
}
if (matrix_[0].size() < n + 1) {
for (auto& mat : matrix_) {
mat.resize(n + 1);
}
}
// The top row and left column are prefixes that can be reached by
// insertions and deletions alone
unsigned int i, j;
for (i = 1; i <= m; ++i) {
matrix_[i][0] = i;
}
for (j = 1; j <= n; ++j) {
matrix_[0][j] = j;
}
// Fill in the rest of the matrix
for (j = 1; j <= n; ++j) {
for (i = 1; i <= m; ++i) {
unsigned int substitution_cost = s[i - 1] == t[j - 1] ? 0 : 1;
matrix_[i][j] =
min3(matrix_[i - 1][j] + 1, // Deletion
matrix_[i][j - 1] + 1, // Insertion
matrix_[i - 1][j - 1] + substitution_cost); // Substitution
}
}
return matrix_[m][n];
}
};
Functor can also be used to simulate defining a local function within a function. Refer to the question and another.
But a local functor can not access outside auto variables. The lambda (C++11) function is a better solution.
To add on, I have used function objects to fit an existing legacy method to the command pattern; (only place where the beauty of OO paradigm true OCP I felt ); Also adding here the related function adapter pattern.
Suppose your method has the signature:
int CTask::ThreeParameterTask(int par1, int par2, int par3)
We will see how we can fit it for the Command pattern - for this, first, you have to write a member function adapter so that it can be called as a function object.
Note - this is ugly, and may be you can use the Boost bind helpers etc., but if you can't or don't want to, this is one way.
// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
:m_Ptr(_Pm) //okay here we store the member function pointer for later use
{}
//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
Also, we need a helper method mem_fun3 for the above class to aid in calling.
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3> mem_fun3 ( _Ret (_Class::*_Pm) (_arg1,_arg2,_arg3) )
{
return (mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3>(_Pm));
}
Now, in order to bind the parameters, we have to write a binder function. So, here it goes:
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
:m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}
//and this is the function object
void operator()() const
{
m_fn(m_ptr,m1,m2,m3);//that calls the operator
}
private:
_Ptr m_ptr;
_Func m_fn;
_arg1 m1; _arg2 m2; _arg3 m3;
};
And, a helper function to use the binder3 class - bind3:
//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}
Now, we have to use this with the Command class; use the following typedef:
typedef binder3<mem_fun3_t<int,T,int,int,int> ,T* ,int,int,int> F3;
//and change the signature of the ctor
//just to illustrate the usage with a method signature taking more than one parameter
explicit Command(T* pObj,F3* p_method,long timeout,const char* key,
long priority = PRIO_NORMAL ):
m_objptr(pObj),m_timeout(timeout),m_key(key),m_value(priority),method1(0),method0(0),
method(0)
{
method3 = p_method;
}
Here is how you call it:
F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3(
&CTask::ThreeParameterTask), task1,2122,23 );
Note: f3(); will call the method task1->ThreeParameterTask(21,22,23);.
The full context of this pattern at the following link
I keep hearing a lot about functors in C++. Can someone give me an overview as to what they are and in what cases they would be useful?
A functor is pretty much just a class which defines the operator(). That lets you create objects which "look like" a function:
// this is a functor
struct add_x {
add_x(int val) : x(val) {} // Constructor
int operator()(int y) const { return x + y; }
private:
int x;
};
// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument
std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
assert(out[i] == in[i] + 1); // for all i
There are a couple of nice things about functors. One is that unlike regular functions, they can contain state. The above example creates a function which adds 42 to whatever you give it. But that value 42 is not hardcoded, it was specified as a constructor argument when we created our functor instance. I could create another adder, which added 27, just by calling the constructor with a different value. This makes them nicely customizable.
As the last lines show, you often pass functors as arguments to other functions such as std::transform or the other standard library algorithms. You could do the same with a regular function pointer except, as I said above, functors can be "customized" because they contain state, making them more flexible (If I wanted to use a function pointer, I'd have to write a function which added exactly 1 to its argument. The functor is general, and adds whatever you initialized it with), and they are also potentially more efficient. In the above example, the compiler knows exactly which function std::transform should call. It should call add_x::operator(). That means it can inline that function call. And that makes it just as efficient as if I had manually called the function on each value of the vector.
If I had passed a function pointer instead, the compiler couldn't immediately see which function it points to, so unless it performs some fairly complex global optimizations, it'd have to dereference the pointer at runtime, and then make the call.
Little addition. You can use boost::function, to create functors from functions and methods, like this:
class Foo
{
public:
void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"
and you can use boost::bind to add state to this functor
boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"
and most useful, with boost::bind and boost::function you can create functor from class method, actually this is a delegate:
class SomeClass
{
std::string state_;
public:
SomeClass(const char* s) : state_(s) {}
void method( std::string param )
{
std::cout << state_ << param << std::endl;
}
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"
You can create list or vector of functors
std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
events.begin(), events.end(),
boost::bind( boost::apply<void>(), _1, e));
There is one problem with all this stuff, compiler error messages is not human readable :)
A Functor is a object which acts like a function.
Basically, a class which defines operator().
class MyFunctor
{
public:
int operator()(int x) { return x * 2;}
}
MyFunctor doubler;
int x = doubler(5);
The real advantage is that a functor can hold state.
class Matcher
{
int target;
public:
Matcher(int m) : target(m) {}
bool operator()(int x) { return x == target;}
}
Matcher Is5(5);
if (Is5(n)) // same as if (n == 5)
{ ....}
Name "functor" has been traditionaly used in category theory long before C++ appeared on the scene. This has nothing to do with C++ concept of functor. It's better to use name function object instead of what we call "functor" in C++. This is how other programming languages call similar constructs.
Used instead of plain function:
Features:
Function object may have state
Function object fits into OOP (it behaves like every other object).
Cons:
Brings more complexity to the program.
Used instead of function pointer:
Features:
Function object often may be inlined
Cons:
Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
Used instead of virtual function:
Features:
Function object (non-virtual) doesn't require vtable and runtime dispatching, thus it is more efficient in most cases
Cons:
Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
Like others have mentioned, a functor is an object that acts like a function, i.e. it overloads the function call operator.
Functors are commonly used in STL algorithms. They are useful because they can hold state before and between function calls, like a closure in functional languages. For example, you could define a MultiplyBy functor that multiplies its argument by a specified amount:
class MultiplyBy {
private:
int factor;
public:
MultiplyBy(int x) : factor(x) {
}
int operator () (int other) const {
return factor * other;
}
};
Then you could pass a MultiplyBy object to an algorithm like std::transform:
int array[5] = {1, 2, 3, 4, 5};
std::transform(array, array + 5, array, MultiplyBy(3));
// Now, array is {3, 6, 9, 12, 15}
Another advantage of a functor over a pointer to a function is that the call can be inlined in more cases. If you passed a function pointer to transform, unless that call got inlined and the compiler knows that you always pass the same function to it, it can't inline the call through the pointer.
For the newbies like me among us: after a little research I figured out what the code jalf posted did.
A functor is a class or struct object which can be "called" like a function. This is made possible by overloading the () operator. The () operator (not sure what its called) can take any number of arguments. Other operators only take two i.e. the + operator can only take two values (one on each side of the operator) and return whatever value you have overloaded it for. You can fit any number of arguments inside a () operator which is what gives it its flexibility.
To create a functor first you create your class. Then you create a constructor to the class with a parameter of your choice of type and name. This is followed in the same statement by an initializer list (which uses a single colon operator, something I was also new to) which constructs the class member objects with the previously declared parameter to the constructor. Then the () operator is overloaded. Finally you declare the private objects of the class or struct you have created.
My code (I found jalf's variable names confusing)
class myFunctor
{
public:
/* myFunctor is the constructor. parameterVar is the parameter passed to
the constructor. : is the initializer list operator. myObject is the
private member object of the myFunctor class. parameterVar is passed
to the () operator which takes it and adds it to myObject in the
overloaded () operator function. */
myFunctor (int parameterVar) : myObject( parameterVar ) {}
/* the "operator" word is a keyword which indicates this function is an
overloaded operator function. The () following this just tells the
compiler that () is the operator being overloaded. Following that is
the parameter for the overloaded operator. This parameter is actually
the argument "parameterVar" passed by the constructor we just wrote.
The last part of this statement is the overloaded operators body
which adds the parameter passed to the member object. */
int operator() (int myArgument) { return myObject + myArgument; }
private:
int myObject; //Our private member object.
};
If any of this is inaccurate or just plain wrong feel free to correct me!
A functor is a higher-order function that applies a function to the parametrized(ie templated) types. It is a generalization of the map higher-order function. For example, we could define a functor for std::vector like this:
template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::vector<U> fmap(F f, const std::vector<T>& vec)
{
std::vector<U> result;
std::transform(vec.begin(), vec.end(), std::back_inserter(result), f);
return result;
}
This function takes a std::vector<T> and returns std::vector<U> when given a function F that takes a T and returns a U. A functor doesn't have to be defined over container types, it can be defined for any templated type as well, including std::shared_ptr:
template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::shared_ptr<U> fmap(F f, const std::shared_ptr<T>& p)
{
if (p == nullptr) return nullptr;
else return std::shared_ptr<U>(new U(f(*p)));
}
Heres a simple example that converts the type to a double:
double to_double(int x)
{
return x;
}
std::shared_ptr<int> i(new int(3));
std::shared_ptr<double> d = fmap(to_double, i);
std::vector<int> is = { 1, 2, 3 };
std::vector<double> ds = fmap(to_double, is);
There are two laws that functors should follow. The first is the identity law, which states that if the functor is given an identity function, it should be the same as applying the identity function to the type, that is fmap(identity, x) should be the same as identity(x):
struct identity_f
{
template<class T>
T operator()(T x) const
{
return x;
}
};
identity_f identity = {};
std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<int> is1 = fmap(identity, is);
std::vector<int> is2 = identity(is);
The next law is the composition law, which states that if the functor is given a composition of two functions, it should be the same as applying the functor for the first function and then again for the second function. So, fmap(std::bind(f, std::bind(g, _1)), x) should be the same as fmap(f, fmap(g, x)):
double to_double(int x)
{
return x;
}
struct foo
{
double x;
};
foo to_foo(double x)
{
foo r;
r.x = x;
return r;
}
std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<foo> is1 = fmap(std::bind(to_foo, std::bind(to_double, _1)), is);
std::vector<foo> is2 = fmap(to_foo, fmap(to_double, is));
Here's an actual situation where I was forced to use a Functor to solve my problem:
I have a set of functions (say, 20 of them), and they are all identical, except each calls a different specific function in 3 specific spots.
This is incredible waste, and code duplication. Normally I would just pass in a function pointer, and just call that in the 3 spots. (So the code only needs to appear once, instead of twenty times.)
But then I realized, in each case, the specific function required a completely different parameter profile! Sometimes 2 parameters, sometimes 5 parameters, etc.
Another solution would be to have a base class, where the specific function is an overridden method in a derived class. But do I really want to build all of this INHERITANCE, just so I can pass a function pointer????
SOLUTION: So what I did was, I made a wrapper class (a "Functor") which is able to call any of the functions I needed called. I set it up in advance (with its parameters, etc) and then I pass it in instead of a function pointer. Now the called code can trigger the Functor, without knowing what is happening on the inside. It can even call it multiple times (I needed it to call 3 times.)
That's it -- a practical example where a Functor turned out to be the obvious and easy solution, which allowed me to reduce code duplication from 20 functions to 1.
Like has been repeated, functors are classes that can be treated as functions (overload operator ()).
They are most useful for situations in which you need to associate some data with repeated or delayed calls to a function.
For example, a linked-list of functors could be used to implement a basic low-overhead synchronous coroutine system, a task dispatcher, or interruptable file parsing.
Examples:
/* prints "this is a very simple and poorly used task queue" */
class Functor
{
public:
std::string output;
Functor(const std::string& out): output(out){}
operator()() const
{
std::cout << output << " ";
}
};
int main(int argc, char **argv)
{
std::list<Functor> taskQueue;
taskQueue.push_back(Functor("this"));
taskQueue.push_back(Functor("is a"));
taskQueue.push_back(Functor("very simple"));
taskQueue.push_back(Functor("and poorly used"));
taskQueue.push_back(Functor("task queue"));
for(std::list<Functor>::iterator it = taskQueue.begin();
it != taskQueue.end(); ++it)
{
*it();
}
return 0;
}
/* prints the value stored in "i", then asks you if you want to increment it */
int i;
bool should_increment;
int doSomeWork()
{
std::cout << "i = " << i << std::endl;
std::cout << "increment? (enter the number 1 to increment, 0 otherwise" << std::endl;
std::cin >> should_increment;
return 2;
}
void doSensitiveWork()
{
++i;
should_increment = false;
}
class BaseCoroutine
{
public:
BaseCoroutine(int stat): status(stat), waiting(false){}
void operator()(){ status = perform(); }
int getStatus() const { return status; }
protected:
int status;
bool waiting;
virtual int perform() = 0;
bool await_status(BaseCoroutine& other, int stat, int change)
{
if(!waiting)
{
waiting = true;
}
if(other.getStatus() == stat)
{
status = change;
waiting = false;
}
return !waiting;
}
}
class MyCoroutine1: public BaseCoroutine
{
public:
MyCoroutine1(BaseCoroutine& other): BaseCoroutine(1), partner(other){}
protected:
BaseCoroutine& partner;
virtual int perform()
{
if(getStatus() == 1)
return doSomeWork();
if(getStatus() == 2)
{
if(await_status(partner, 1))
return 1;
else if(i == 100)
return 0;
else
return 2;
}
}
};
class MyCoroutine2: public BaseCoroutine
{
public:
MyCoroutine2(bool& work_signal): BaseCoroutine(1), ready(work_signal) {}
protected:
bool& work_signal;
virtual int perform()
{
if(i == 100)
return 0;
if(work_signal)
{
doSensitiveWork();
return 2;
}
return 1;
}
};
int main()
{
std::list<BaseCoroutine* > coroutineList;
MyCoroutine2 *incrementer = new MyCoroutine2(should_increment);
MyCoroutine1 *printer = new MyCoroutine1(incrementer);
while(coroutineList.size())
{
for(std::list<BaseCoroutine *>::iterator it = coroutineList.begin();
it != coroutineList.end(); ++it)
{
*it();
if(*it.getStatus() == 0)
{
coroutineList.erase(it);
}
}
}
delete printer;
delete incrementer;
return 0;
}
Of course, these examples aren't that useful in themselves. They only show how functors can be useful, the functors themselves are very basic and inflexible and this makes them less useful than, for example, what boost provides.
Functors are used in gtkmm to connect some GUI button to an actual C++ function or method.
If you use the pthread library to make your app multithreaded, Functors can help you.
To start a thread, one of the arguments of the pthread_create(..) is the function pointer to be executed on his own thread.
But there's one inconvenience. This pointer can't be a pointer to a method, unless it's a static method, or unless you specify it's class, like class::method. And another thing, the interface of your method can only be:
void* method(void* something)
So you can't run (in a simple obvious way), methods from your class in a thread without doing something extra.
A very good way of dealing with threads in C++, is creating your own Thread class. If you wanted to run methods from MyClass class, what I did was, transform those methods into Functor derived classes.
Also, the Thread class has this method:
static void* startThread(void* arg)
A pointer to this method will be used as an argument to call pthread_create(..). And what startThread(..) should receive in arg is a void* casted reference to an instance in heap of any Functor derived class, which will be casted back to Functor* when executed, and then called it's run() method.
Except for used in callback, C++ functors can also help to provide a Matlab liking access style to a matrix class. There is a example.
A big advantage of implementing functions as functors is that they can maintain and reuse state between calls. For example, many dynamic programming algorithms, like the Wagner-Fischer algorithm for calculating the Levenshtein distance between strings, work by filling in a large table of results. It's very inefficient to allocate this table every time the function is called, so implementing the function as a functor and making the table a member variable can greatly improve performance.
Below is an example of implementing the Wagner-Fischer algorithm as a functor. Notice how the table is allocated in the constructor, and then reused in operator(), with resizing as necessary.
#include <string>
#include <vector>
#include <algorithm>
template <typename T>
T min3(const T& a, const T& b, const T& c)
{
return std::min(std::min(a, b), c);
}
class levenshtein_distance
{
mutable std::vector<std::vector<unsigned int> > matrix_;
public:
explicit levenshtein_distance(size_t initial_size = 8)
: matrix_(initial_size, std::vector<unsigned int>(initial_size))
{
}
unsigned int operator()(const std::string& s, const std::string& t) const
{
const size_t m = s.size();
const size_t n = t.size();
// The distance between a string and the empty string is the string's length
if (m == 0) {
return n;
}
if (n == 0) {
return m;
}
// Size the matrix as necessary
if (matrix_.size() < m + 1) {
matrix_.resize(m + 1, matrix_[0]);
}
if (matrix_[0].size() < n + 1) {
for (auto& mat : matrix_) {
mat.resize(n + 1);
}
}
// The top row and left column are prefixes that can be reached by
// insertions and deletions alone
unsigned int i, j;
for (i = 1; i <= m; ++i) {
matrix_[i][0] = i;
}
for (j = 1; j <= n; ++j) {
matrix_[0][j] = j;
}
// Fill in the rest of the matrix
for (j = 1; j <= n; ++j) {
for (i = 1; i <= m; ++i) {
unsigned int substitution_cost = s[i - 1] == t[j - 1] ? 0 : 1;
matrix_[i][j] =
min3(matrix_[i - 1][j] + 1, // Deletion
matrix_[i][j - 1] + 1, // Insertion
matrix_[i - 1][j - 1] + substitution_cost); // Substitution
}
}
return matrix_[m][n];
}
};
Functor can also be used to simulate defining a local function within a function. Refer to the question and another.
But a local functor can not access outside auto variables. The lambda (C++11) function is a better solution.
To add on, I have used function objects to fit an existing legacy method to the command pattern; (only place where the beauty of OO paradigm true OCP I felt ); Also adding here the related function adapter pattern.
Suppose your method has the signature:
int CTask::ThreeParameterTask(int par1, int par2, int par3)
We will see how we can fit it for the Command pattern - for this, first, you have to write a member function adapter so that it can be called as a function object.
Note - this is ugly, and may be you can use the Boost bind helpers etc., but if you can't or don't want to, this is one way.
// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
:m_Ptr(_Pm) //okay here we store the member function pointer for later use
{}
//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
Also, we need a helper method mem_fun3 for the above class to aid in calling.
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3> mem_fun3 ( _Ret (_Class::*_Pm) (_arg1,_arg2,_arg3) )
{
return (mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3>(_Pm));
}
Now, in order to bind the parameters, we have to write a binder function. So, here it goes:
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
:m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}
//and this is the function object
void operator()() const
{
m_fn(m_ptr,m1,m2,m3);//that calls the operator
}
private:
_Ptr m_ptr;
_Func m_fn;
_arg1 m1; _arg2 m2; _arg3 m3;
};
And, a helper function to use the binder3 class - bind3:
//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}
Now, we have to use this with the Command class; use the following typedef:
typedef binder3<mem_fun3_t<int,T,int,int,int> ,T* ,int,int,int> F3;
//and change the signature of the ctor
//just to illustrate the usage with a method signature taking more than one parameter
explicit Command(T* pObj,F3* p_method,long timeout,const char* key,
long priority = PRIO_NORMAL ):
m_objptr(pObj),m_timeout(timeout),m_key(key),m_value(priority),method1(0),method0(0),
method(0)
{
method3 = p_method;
}
Here is how you call it:
F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3(
&CTask::ThreeParameterTask), task1,2122,23 );
Note: f3(); will call the method task1->ThreeParameterTask(21,22,23);.
The full context of this pattern at the following link
I'm new to smart pointers and I would be really grateful if somebody could give me a hint whether the way I'm handling smart pointers as class members is correct.
More precisely, the solution that I would like to achieve is in the context of class polymorphism and should be ideally exception-safe.
Given a container of heterogeneuous objects (std::vector<shared_ptr<CBase> > my_vector), the usual way to add elements is: my_vector.push_back( shared_ptr<CBase>(new CChild(1))), so that later on, one can call the member function of the specific derived class by doing: my_vector[0]->doSomething().
What I would like to achieve is to add stack objects to the vector and still being able to do polymorphism. Intuitively sth. like: CChild<float> obj1(1); my_vector.push_back(obj1). To solve that, I'm using now the Virtual Constructor Idiom: CChild obj1(1); my_vector.push_back(obj1.clone());.
Note that in some of my derived classes, I've static member functions that create objects, e.g: CChild<float> obj1 = CChild<float>::initType2(1);
Because of requirement issues and also to have a clean interface, I've now a new class CFoo<T> that has as data member a smart pointer to the CBase<T> class. The idea is that besides containing other new private members,
this class encapsulates/handles the smart pointers to the derived objects, such that I'm allowed to do sth. like: CFoo<float> myfoo(CChild<float>::initType2(1)); my_vector.push_back(myfoo);. This means that the container is now of type vector<CFoo<T> > instead of type vector<shared_ptr<CBase> >
It's in this context, that I would like to know how to implement the constructors for a class with smart pointers as class members? What about the implementation of the operator = following the copy-swap idiom? Below, I give some ilustrations of my class design:
template < typename T >
class CBase{
public:
CBase(){};
virtual ~CBase(){};
...
virtual CBase<T> * clone() const = 0;
virtual CBase<T> * create() const = 0;
};
template < typename T >
class CChild1 : public CBase{
public:
...
CChild1<T> * clone() const { return new CChild1<T>(*this); }
CChild1<T> * create() const { return new CChild1<T>(); }
static CChild1 initType1(double, double);
static CChild1 initType2(int);
};
template < typename T >
struct type{
typedef std::tr1::shared_ptr<T> shared_ptr;
};
template < typename T >
class CFoo{
public:
CFoo();
CFoo( const CBase<T> &, int = 0 );
CFoo( const CFoo<T> & );
void setBasePtr( const CBase<T> & );
void swap( CFoo<T> & );
CFoo<T> & operator = ( CFoo<T> );
...
~CFoo();
private:
typename type<CBase<T> >::shared_ptr m_ptrBase;
int m_nParam;
};
template < typename T >
CFoo<T>::CFoo()
:m_nParam(0)
// How shall I handle here the "m_ptrBase" class member? e.g point it to NULL?
{
}
template < typename T >
CFoo<T>::CFoo(const CBase<T> & refBase, int nParam)
:m_ptrBase(refBase.clone()), // Is this initialization exception-safe?
m_nParam(nParam)
{
}
template < typename T >
CFoo<T>::CFoo(const CFoo<T> & refFoo)
:m_ptrBase(refFoo.m_ptrBase),
m_nParam(refFoo.m_nParam)
{
}
template < typename T >
void CFoo<T>::setBasePtr( const CBase<T> & refBase ){
// ??? I would like to do sth. like: m_ptrBase(refBase.clone())
}
template < typename T >
CFoo<T>::~CFoo(){
// The memory is going to be freed by the smart pointer itself and therefore
// the destructor is empty, right?
}
template < typename T >
void CFoo<T>::swap( CFoo<T> & refFoo ){
//does this here makes sense?
using std::swap;
swap(m_ptrBase, refFoo.m_ptrBase);
swap(m_nParam, refFoo.m_nParam);
}
template < typename T >
CFoo<T> & CFoo<T>::operator = ( CFoo<T> copyFoo ){
copyFoo.swap(*this);
return (*this);
}
Below an example on what I would like to intuitively achieve. First, I fill the container with CFoo<float> objects that contain smart pointers to derived classes, besides another integer class member (Note that all this is only illustrative).
std::vector<CFoo<float> > my_bank;
for (int b=0; b < 3; b++){
float x = b*sqrt(2);
my_bank.push_back( new CFoo<float>( CChild1<float>::initType2(x), b) );
}
for (double s= 1.0; s<= 8.0; s *= 2.0){
my_bank.push_back( new CFoo<float>( CChild2<float>::initType2(x), 0) );
}
Once, the container is filled, I would like to do some operations, calling to virtual functions, e.g. doSomething that are specialized in each derived class.
for (int i=0; i < (int)my_bank.size(); i++){
int b = my_bank[i].m_nParam;
CBase<float>* myChild = my_bank[i].m_ptrBase;
myChild->doSomething( param1, param2, param3, ..., b);
}
I really don't know how to approach this. I don't understand half the interface requirements you've listed, so consider this an experimental answer that may not relate to your problem at all.
I suggest that you tell me what exactly is missing from my approach, and I can amend it. I'll omit templates for now, since they don't seem to be relevant to the problem.
So, without further ado, the simplest start uses a container of smart pointers:
#include <vector>
#include <memory>
struct Base
{
virtual void f();
};
typedef std::shared_ptr<Base> BasePtr;
typedef std::vector<BasePtr> BaseContainer;
struct DerivedA : Base
{
virtual void f();
// ...
};
// further derived classes
Usage:
int main()
{
BaseContainer v;
v.push_back(BasePtr(new DerivedB));
v.push_back(BasePtr(new DerivedC(true, 'a', Blue)));
BasePtr x(new DerivedA);
some_func(x);
x->foo()
v.push_back(x);
v.front()->foo();
}
If you happen to have some automatic object somewhere, you can insert a copy:
DerivedD d = get_some_d();
v.push_back(BasePtr(new DerivedD(d)));
To iterate:
for (BaseContainer::const_iterator it = v.begin(), end = v.end(); it != end; ++it)
{
(*it)->foo();
}
Update: If you want to initialize an object after construction, you can do something like this:
{
DerivedE * p = new DerivedE(x, y, z);
p->init(a, b, c);
v.push_back(BasePtr(p));
}
Or, if the init function is virtual, even simpler:
v.push_back(BasePtr(new DerivedE(x, y, z)));
v.back()->init(a, b, c);
2nd Update: Here's how a derived object might look like:
struct DerivedCar : Base
{
enum EType { None = 0, Porsche, Dodge, Toyota };
DerivedCar(EType t, bool a, unsigned int p)
: Base(), type(t), automatic_transmission(a), price(p)
{
std::cout << "Congratulations, you know own a " << names[type] << "!\n"; }
}
private:
EType type;
bool automatic_transmission;
unsigned int price;
static const std::unordered_map<EType, std::string> names; // fill it in elsewhere
};
Usage: Base * b = new DerivedCar(DerivedCar::Porsche, true, 2000);
3rd Update: This one is unconnected, just an illustration of how to use lookup tables in favour of switch statements. Suppose we have lots of similar functions (same signature) that we want to use based on some integer:
struct Foo
{
void do_a();
void do_b();
// ...
void do(int n)
{
switch (n) {
case 2: do_a(); break;
case 7: do_b(); break;
}
}
};
Instead of the switch, we can register all functions in a lookup table. Here I'm assuming C++11 support:
struct Foo
{
// ...
static const std::map<int, void(Foo::*)()> do_fns;
void do(int n)
{
auto it = do_fns.find(n);
if (it != do_fns.end()) { (this->**it)(); }
}
};
const std::map<nt, void(Foo::*)()> Foo::do_fns {
{ 3, &Foo::do_a },
{ 7, &Foo::do_b },
// ...
};
Basically, you turn static code into container data. That's always a Good Thing. This is now easily scalable; you just add new functions to the lookup map as they come along. No need to touch the actual do() code again!