Stacked people.
Iam trying to implement an observer(esque?) pattern for my program. I have a component which stores what functions should be called if an event occours. My prolem is that i dont know how should i erase my function from the container, if the need arises. Tried storing the functions by reference, but iam not sure how to do that(or if thats possible.)
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
enum class EVENT_TYPE{
anEvent
};
class EventableComponent{
map<EVENT_TYPE, vector<function<void()>>> listeners;
public:
void trigger(EVENT_TYPE _et){
for(auto& it : listeners[_et]){
it();
}
}
void registerListener(EVENT_TYPE _et, function<void()> _fn){
listeners[_et].push_back(_fn);
};
void removeListener(EVENT_TYPE _et, function<void()> _fn){
//error C2678: binary '==' : no operator found which takes a left-hand operand of type 'std::function<void (void)>'
//(or there is no acceptable conversion)
listeners[_et].erase(remove(listeners[_et].begin(), listeners[_et].end(), _fn), listeners[_et].end());
};
};
int main(){
EventableComponent ec;
// this would become a member function for a class somewhere down the line
auto fn = [](){cout << "Hello.\n"; };
ec.registerListener(EVENT_TYPE::anEvent, fn);
ec.trigger(EVENT_TYPE::anEvent);
ec.removeListener(EVENT_TYPE::anEvent, fn);
ec.trigger(EVENT_TYPE::anEvent);
cin.get();
return 0;
};
Your problem can be reduced to the fact that two std::function instances cannot be compared for equality. std::remove requires operator==, and std::function does not have it. See "Why is std::function not equality comparable?".
Consider the following situation.
Let's say you defined two lambdas in your main:
auto fn = [](){cout << "Hello.\n"; };
auto fn2 = [](){cout << "Hello.\n"; };
Now, are those two equal or not? They do the same thing, but perhaps this is sheer coincidence. Would they become unequal if the second "Hello" became "Hello2"? Would they become unequal if the second one was no longer a lambda but a real function void f()?
The thing is that there can be no generally useful definition of equality for function objects, so it's up to you to define what equality really means in the context of your program.
You have several options to solve the problem at hand. One would be to operate on pointers to std::function objects. Pointers can be compared, and proper use of std::unique_ptr makes sure that deallocation is handled correctly.
Or you assign an identifier to every std::function you use. See the following modified example of your code in which direct storage of std::function<void()> in the vector is replaced with a custom type EventFunction that maps an int to the function object. The example uses std::remove_if to compare only the ints:
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
enum class EVENT_TYPE{
anEvent
};
struct EventFunction {
function<void()> f;
int id;
};
class EventableComponent{
map<EVENT_TYPE, vector<EventFunction>> listeners;
public:
void trigger(EVENT_TYPE _et){
for(auto& it : listeners[_et]){
it.f();
}
}
void registerListener(EVENT_TYPE _et, EventFunction _fn){
listeners[_et].push_back(_fn);
};
void removeListener(EVENT_TYPE _et, int function_id){
//error C2678: binary '==' : no operator found which takes a left-hand operand of type 'std::function<void (void)>'
//(or there is no acceptable conversion)
listeners[_et].erase(remove_if(listeners[_et].begin(), listeners[_et].end(),
[&](EventFunction const& e) { return e.id == function_id; }), listeners[_et].end());
};
};
int main(){
EventableComponent ec;
// this would become a member function for a class somewhere down the line
auto fn = [](){cout << "Hello.\n"; };
ec.registerListener(EVENT_TYPE::anEvent, EventFunction{ fn, 1 });
ec.trigger(EVENT_TYPE::anEvent);
ec.removeListener(EVENT_TYPE::anEvent, 1);
ec.trigger(EVENT_TYPE::anEvent);
};
Tried storing the functions by reference, but iam not sure how to do
that(or if thats possible.)
It's not possible because you cannot store references in standard-library containers. But I suppose the idea is similar to the one with pointers I mentioned above.
Related
Is it possible to use lambda for hashing in hashed_<non>_unique interface for boost::multi_index?
See this example: https://godbolt.org/z/1voof3
I also saw this: How to use lambda function as hash function in unordered_map? where the answer says:
You need to pass lambda object to unordered_map constructor since lambda types are not default constructible.
and I'm not sure is it even possible to do for the given example on godbolt.
Starting with C++20, yes, you can: https://godbolt.org/z/fTbzPP (note f is declared as auto const hash_f, without a &).
As for #sehe's claim that multi_index_containers can't be passed instances of hash objects (or other intervening function objects) at construction time, the claim is incorrect: they can, although the interface is somewhat complicated:
Live Coliru Demo
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <functional>
struct non_default_ctble_hash
{
non_default_ctble_hash(std::size_t n):n{n}{}
template<typename T>
std::size_t operator()(const T& x){return std::hash<T>{}(x)*n;}
std::size_t n;
};
using namespace boost::multi_index;
using container=multi_index_container<
int,
indexed_by<
hashed_unique<identity<int>,non_default_ctble_hash>
>
>;
int main()
{
container::ctor_args_list cal{
{0,identity<int>{},non_default_ctble_hash{666},std::equal_to<int>{}}
};
container c(cal);
}
I don't think you can. With a standard container you would have had to supply the actual instance to the constructor. However, MultiIndex doesn't afford that:
docs
As explained in the index concepts section, indices do not have public constructors or destructors. Assignment, on the other hand, is provided. Upon construction, max_load_factor() is 1.0.
Loophole?
You can perhaps get away with a locally defined class:
auto const hash_f = [](int const& n) { return std::hash<int>()(n); };
struct HashType : decltype(hash_f) {};
using AnimalsMultiIndex = multi_index_container<
Animal, indexed_by<hashed_non_unique<
tag<animal_legs>, member<Animal, LegsType, &Animal::legs>,
HashType>>>;
AnimalsMultiIndex animals;
Which does work: c++20 required
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/multi_index_container.hpp>
#include <iostream>
#include <string>
using namespace boost::multi_index;
using LegsType = int;
struct Animal {
std::string name;
LegsType legs;
};
// tags
struct animal_legs {};
int main() {
// using lambda doesn't work for hashing
auto const hash_f = [](int const& n) { return std::hash<int>()(n); };
struct HashType : decltype(hash_f) {};
using AnimalsMultiIndex = multi_index_container<
Animal, indexed_by<hashed_non_unique<
tag<animal_legs>, member<Animal, LegsType, &Animal::legs>,
HashType>>>;
AnimalsMultiIndex animals;
animals.insert({ "cat", 4 });
auto const& legs_index = animals.get<animal_legs>();
int num_of_legs = 4;
std::cout << "Number of animals that have " << num_of_legs
<< " legs is: " << legs_index.count(num_of_legs) << '\n';
}
Prints
Number of animals that have 4 legs is: 1
I have been playing around with function pointers in c++ and seem to have found a bit of a problem. I made a demo to reproduce the error in a simple example.
I have the header file
class MyClass
{
public:
void MyFunction(int i);
MyClass();
~MyClass();
};
and the cpp file
#include "MyClass.h"
#include <iostream>
#include <functional>
using namespace std;
MyClass::MyClass()
{
//doesn't work
function<void(int)> func = &MyClass::MyFunction;
}
void MyClass::MyFunction(int i)
{
cout << i << endl;
}
In the constructor of the cpp file I am trying to create a pointer to MyFunction. It gives the error error C2664: 'void std::_Func_class<_Ret,int>::_Set(std::_Func_base<_Ret,int> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,int> *' in the functional file at line 506. It works fine with a parameterless method, but not with them. Does anyone know why, and how to resolve it?
You can use this and bind the object being constructed to the function. For instance, if your constructor looked like this:
MyClass::MyClass()
{
function<void(int)> func = bind(&MyClass::MyFunction, this, placeholders::_1);
func(6);
}
And you created a MyClass instance:
MyClass instance;
Then 6 will be printed to stdout.
You can also use std::mem_fn in C++11, which wraps a member function/variable into a callable closure
#include <iostream>
#include <functional>
class MyClass
{
public:
MyClass()
{
auto func = std::mem_fn(&MyClass::MyFunction);
func(this, 42); // call it on the current instance
}
void MyFunction(int i)
{
std::cout << i << std::endl;
}
};
int main()
{
MyClass foo;
}
or, you can explicitly specify the instance you're calling the pointer to member function
MyClass()
{
auto func = &MyClass::MyFunction;
(this->*func)(42); // call it on the current instance
}
In particular, note that std::function<void(int)> is not convertible to a pointer to member function. See related Using generic std::function objects with member functions in one class
That's why using auto with std::mem_fn gets rid of all the pain.
I want to create a boost function object of the following signature:
void (int, boost::uuid);
However, I would like to bind it to a function of the following form:
void (SomeType, boost::uuid)
Where the SomeType argument comes from another function call, so that if I were to call it straight out it would look like:
SomeType myOtherFunction(int);//Prototype
...
myFunction(myOtherFunction(int), myUUID);
In other words, I want the top level function object to completely hide the concept of SomeType and the call to myOtherFunction from the user. Is there a way to do this with one or more boost::function objects created with boost::bind calls?
Functional composition: Live On Coliru
#include <boost/uuid/uuid.hpp>
struct SomeType {};
SomeType myOtherFunction(int) { return SomeType(); }
void foo(SomeType, boost::uuids::uuid) {}
#include <boost/bind.hpp>
#include <boost/function.hpp>
int main()
{
boost::function<void(int, boost::uuids::uuid)> composed;
composed = boost::bind(foo, boost::bind(myOtherFunction, _1), _2);
}
Anyways, in c++11 you'd write [](int i, uuid u) { return foo(myOtherFunction(i), u); } of course
Item 25 in Effective c++ third edition, Scott Meyers suggests to implement swap in the same namespace as the class, and then when swapping to employ the using std::swap, and there the author says :
For example, if you were to write the call to swap this way:
std::swap(obj1,obj2); // the wrong way to call swap
you'd force the compiler to consider only the swap in std, thus
eliminating the possibility of getting a more appropriate T-specific
version defined elsewhere. Alas, some misguided programmers do qualify
calls to swap in this way, and that is why it's important to totally
specialize std::swap for your classes.
The author recommends to always swap objects this way :
#include <iostream>
#include <utility>
#define CUSTOM_SWAP
namespace aaa{
struct A
{
};
#ifdef CUSTOM_SWAP
void swap( A&, A& )
{
std::cout<<"not std::swap"<<std::endl;
}
#endif
}
int main()
{
using std::swap; // add std::swap to a list of possible resolutions
aaa::A a1;
aaa::A a2;
swap(a1,a2);
}
Why isn't std::swap in global namespace? That way, it would be simpler to add custom swap functions.
Probably because the standard says so, 17.6.1.1/2:
All library entities except macros, operator new and operator delete are defined within the namespace std or namespaces nested within namespace std.
And you would still need to put using ::swap sometimes, so it would introduce even more special cases. Here I use func instead of swap - http://ideone.com/WAWBfZ :
#include <iostream>
using namespace std;
template <class T>
auto func(T) -> void
{
cout << "::f" << endl;
}
namespace my_ns {
struct my_struct {};
auto func(my_struct) -> void
{
cout << "my_ns::func" << endl;
}
auto another_func() -> void
{
// won't compile without `using ::func;`
func(123);
}
}
auto main() -> int {}
fails with
prog.cpp: In function ‘void my_ns::another_func()’:
prog.cpp:21:17: error: could not convert ‘123’ from ‘int’ to ‘my_ns::my_struct’
func(123);
The following code causes cl.exe to crash (MS VS2005).
I am trying to use boost bind to create a function to a calls a method of myclass:
#include "stdafx.h"
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <functional>
class myclass {
public:
void fun1() { printf("fun1()\n"); }
void fun2(int i) { printf("fun2(%d)\n", i); }
void testit() {
boost::function<void ()> f1( boost::bind( &myclass::fun1, this ) );
boost::function<void (int)> f2( boost::bind( &myclass::fun2, this ) ); //fails
f1();
f2(111);
}
};
int main(int argc, char* argv[]) {
myclass mc;
mc.testit();
return 0;
}
What am I doing wrong?
Use the following instead:
boost::function<void (int)> f2( boost::bind( &myclass::fun2, this, _1 ) );
This forwards the first parameter passed to the function object to the function using place-holders - you have to tell Boost.Bind how to handle the parameters. With your expression it would try to interpret it as a member function taking no arguments.
See e.g. here or here for common usage patterns.
Note that VC8s cl.exe regularly crashes on Boost.Bind misuses - if in doubt use a test-case with gcc and you will probably get good hints like the template parameters Bind-internals were instantiated with if you read through the output.
Boost.Bind is a library that simplifies and generalizes capabilities that originally required std::bind1st() and std::bind2nd()
Example 1.1: std::for_each() with a compatible function
#include <vector>
#include <algorithm>
#include <iostream>
void print(int i)
{
std::cout << i << '\n';
}
int main()
{
std::vector<int> v{1, 3, 2};
std::for_each(v.begin(), v.end(), print);
}
The third parameter of std::for_each() is a function or function object that expects a sole parameter. In Example 1.1, std::for_each() passes the numbers in the container v as sole parameters, one after another, to print().
If you need to pass in a function whose signature doesn’t meet the requirements of an algorithm, it gets more difficult. For example, if you want print() to accept an output stream as an additional parameter, you can no longer use it as is with std::for_each().
Example 1.2. std::for_each() with std::bind1st()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
class print : public std::binary_function<std::ostream*, int, void>
{
public:
void operator()(std::ostream *os, int i) const
{
*os << i << '\n';
}
};
int main()
{
std::vector<int> v{1, 3, 2};
std::for_each(v.begin(), v.end(), std::bind1st(print{}, &std::cout));
}
Like Example 1.1, Example 1.2 writes all numbers in v to standard output. However, this time, the output stream is passed to print() as a parameter. To do this, the function print() is defined as a function object derived from std::binary_function.
With Boost.Bind, you don’t need to transform print() from a function to a function object. Instead, you use the function template boost::bind(), which is defined in boost/bind.hpp.
Example 1.3: std::for_each() with boost::bind()
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
void print(std::ostream *os, int i)
{
*os << i << '\n';
}
int main()
{
std::vector<int> v{1, 3, 2};
std::for_each(v.begin(), v.end(), boost::bind(print, &std::cout, _1));
}
Example 1.3 uses print() as a function, not as a function object. Because print() expects two parameters, the function can’t be passed directly to std::for_each(). Instead, boost::bind() is passed to std::for_each() and print() is passed as the first parameter to boost::bind().
Since print() expects two parameters, those two parameters must also be passed to boost::bind(). They are a pointer to std::cout and _1.
_1 is a placeholder. Boost.Bind defines placeholders from _1 to _9. These placeholders tell boost::bind() to return a function object that expects as many parameters as the placeholder with the greatest number. If, as in Example 1.3, only the placeholder _1 is used, boost::bind() returns a unary function object – a function object that expects a sole parameter. This is required in this case since std::for_each() passes only one parameter.
std::for_each() calls a unary function object. The value passed to the function object – a number from the container v – takes the position of the placeholder _1. boost::bind() takes the number and the pointer to std::cout and forwards them to print().
Please note that boost::bind(), like std::bind1st() and std::bind2nd(), takes parameters by value. To prevent the calling program from trying to copy std::cout, print() expects a pointer to a stream. Boost.Ref provides a function which allows you to pass a parameter by reference.
Example 1.4 illustrates how to define a binary function object with boost::bind(). It uses the algorithm std::sort(), which expects a binary function as its third parameter.
Example 1.4. std::sort() with boost::bind()
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
bool compare(int i, int j)
{
return i > j;
}
int main()
{
std::vector<int> v{1, 3, 2};
std::sort(v.begin(), v.end(), boost::bind(compare, _1, _2));
for (int i : v)
std::cout << i << '\n';
}
In Example 1.4, a binary function object is created because the placeholder _2 is used. The algorithm std::sort() calls this binary function object with two values from the container v and evaluates the return value to sort the container. The function compare() is defined to sort v in descending order.
Since compare() is a binary function, it can be passed to std::sort() directly. However, it can still make sense to use boost::bind() because it lets you change the order of the parameters. For example, you can use boost::bind() if you want to sort the container in ascending order but don’t want to change compare()
Example 1.5. std::sort() with boost::bind() and changed order of placeholders
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
bool compare(int i, int j)
{
return i > j;
}
int main()
{
std::vector<int> v{1, 3, 2};
std::sort(v.begin(), v.end(), boost::bind(compare, _2, _1));
for (int i : v)
std::cout << i << '\n';
}
The following works for me.
class test_component
{
private:
void on_wait_complete(const int i);
};
void test_component::on_wait_complete (const int i)
{
cout << "on_wait_complete was called" << endl;
return;
}
int main()
{
// timerPtr_ is a variable declared in class test_component.
timerPtr_->async_wait(boost::bind(&test_component::on_wait_complete, this, _1));
}