std::vector of std::function - function

I have the following:
typedef std::function<void(const EventArgs&)> event_type;
class Event : boost::noncopyable
{
private:
typedef std::vector<event_type> EventVector;
typedef EventVector::const_iterator EventVector_cit;
EventVector m_Events;
public:
Event()
{
}; // eo ctor
Event(Event&& _rhs) : m_Events(std::move(_rhs.m_Events))
{
}; // eo mtor
// operators
Event& operator += (const event_type& _ev)
{
assert(std::find(m_Events.begin(), m_Events.end(), _ev) == m_Events.end());
m_Events.push_back(_ev);
return *this;
}; // eo +=
Event& operator -= (const event_type& _ev)
{
EventVector_cit cit(std::find(m_Events.begin(), m_Events.end(), _ev));
assert(cit != m_Events.end());
m_Events.erase(cit);
return *this;
}; // eo -=
}; // eo class Event
And during compilation:
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(41): error C2451: conditional expression of type 'void' is illegal
1> Expressions of type void cannot be converted to other types
Now, I understand this is because of what is being stored in the vector and the operator ==. Is there another way to store std::function in an STL container? Do I need to wrap it up in something else?

You can store boost::function in the vector, provided you don't use std::find. Since you seem to need this, wrapping the function in its own class with equality would be probably the best.
class EventFun
{
int id_;
boost::function<...> f_;
public:
...
bool operator==(const EventFun& o) const { return id_==o.id_; } // you get it...
};
Note that this requires you maintain the id_ in a sane way (eg. two different EventFuns will have different id_s, etc.).
Another possibility would be to store boost::functions with a tag the client would remember and use to identify the particular function on deleting it.

Related

how to do template class constructors as forward declaration

I am migrating my code from c++17 to c++20 and need to use require instead of std::enable_if...
How to define class constructors as forward declaration with c++20 that uses require keyword on following sample ?
#include <type_traits>
class CChMyBaseClass {
};
template <
typename _ChClass,
typename _ChFunction>
class CChMyClass : public CChMyBaseClass {
private:
_ChFunction m_ChFunction;
public:
// how to do forward declaration ?
CChMyClass()
requires (std::is_member_function_pointer<_ChFunction>::value)
: CChMyBaseClass() {
}
// how to do forward declaration ?
CChMyClass()
requires (!std::is_member_function_pointer<_ChFunction>::value)
: CChMyBaseClass()
, m_ChFunction(
nullptr) {
}
};
class CChTestClass {
public:
void ChTest() {
}
};
void ChTest() {
}
int main() {
CChMyClass<CChTestClass, decltype(&CChTestClass::ChTest)> CChMyClass1();
CChMyClass<CChTestClass, decltype(&ChTest)> CChMyClass2();
return 0;
}
It's really not different from any other type of forward declaration. Just write:
template <typename _ChClass, typename _ChFunction>
class CChMyClass: public CChMyBaseClass {
...
CChMyClass() requires (std::is_member_function_pointer<_ChFunction>::value);
CChMyClass() requires (!std::is_member_function_pointer<_ChFunction>::value);
...
};
I think the difficulty is rather in the actual function definitions. But even that is not too difficult if you think about it. You just need to include the template parameters and the requires clause again:
template <typename _ChClass, typename _ChFunction>
CChMyClass<_ChClass, _ChFunction>::CChMyClass()
requires (std::is_member_function_pointer<_ChFunction>::value)
: CChMyBaseClass(), m_ChFunction(...) {
...
};
Note that in your example, you did not declare two instances of CChMyClass in main(), but rather forward declared two functions that had a CChMyClass as a return type (this is known as the most vexing parse). Just omit the () at the end, or use braces instead.

"Failed to specialize function template" when trying to pass member function of another class

I have been trying to assign class's member function to a std::function but it throws compile time error Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)
Below is the header file of that class :
class TypeAnalysis {
public:
bool AnalysisHelper(std::string filePath);
void createTypeTable(std::string dir, std::string pattern, size_t nThread = 3);
std::vector<std::string> getFiles(std::string dir, std::vector<std::string> patterns);
private:
};
And below is createtypeTable function where I am assigning AnalysisHelper method to std::fnuction object.
void TypeAnalysis::createTypeTable(std::string dir, std::string pattern, size_t nThread)
{
Threadpool<bool, std::string> tp(10);
DataContext dc;
tp.start();
std::vector<std::string> patterns = SH::split(pattern);
std::vector<std::string> files = getFiles(dir, patterns);
std::function<bool(std::string)> w = &TypeAnalysis::AnalysisHelper; //I think issue is here
try {
if (files.size() > 0) {
for (size_t i = 0; i < files.size(); i++) {
WorkItem<bool, std::string> *wi1 = new WorkItem<bool, std::string>(&w, &files[i]);
tp.doWork(wi1);
}
}
}
catch (std::exception ex) {
std::cout << ex.what();
return;
}
tp.doWork(nullptr);
tp.wait();
DataContext::getContextThreadPool().doWork(nullptr);
}
When I tried to do the same without any class definition (AnalysisHelper was Glabal function and main had same body as createTypeTable), it worked fine.
Any idea whats wrong?
Yes, the problem is in this line:
std::function<bool(std::string)> w = &TypeAnalysis::AnalysisHelper;
I can not see this as correct operation. You are referencing a member function of a class. This member function may need to edit or read one of the member variables of that class. It is not a free function. It is part of the class which should be called for a specific object. So it is normal that C++ denied that.
Edit:
I found this https://isocpp.org/wiki/faq/pointers-to-members#memfnptr-vs-fnptr
How do I pass a pointer-to-member-function to a signal handler, X event callback, system call that starts a thread/task, etc?
Don’t.
Because a member function is meaningless without an object to invoke it on,
you can’t do this directly (if The X Window System was rewritten in
C++, it would probably pass references to objects around, not just
pointers to functions; naturally the objects would embody the required
function and probably a whole lot more)
Issue was I was not binding the method to any object. Changing
std::function<bool(std::string)> w = &TypeAnalysis::AnalysisHelper;
to
std::function<bool(std::string)> w = [=](std::string file) { return this->AnalysisHelper(file); };
worked.

Double linked list delete back node function

/* There is something wrong with the function delete_back(); I think something wrong with the remove function 3 parts.
Also remove_ele() I do not how to do it, thanks.
why I use the same method to delete element does not work
*/
#include <iostream>
using namespace std;
template<class T>
class doulinked
{
private:
doulinked *head;
doulinked *tail;
doulinked *prev;
doulinked *next;
T data;
public:
doulinked()
{
head=tail=prev=next=NULL;
T data;
}
void Inlist (doulinked *head);
void add(T d);
void insert_node();
void remove(doulinked* v);
void push_tail(T d);
void delete_front();
void delete_back();
void remove_ele (T d);
template <class U>
friend ostream & operator<<(ostream & os, const doulinked<U> & dll);
};
template<class U>
ostream & operator<<(ostream & os,const doulinked<U> & dll)
{
doulinked<U> * tmp = dll.head;
while (tmp)
{
os << tmp->data << " ";
tmp = tmp->next;
}
return os;
}
template<class T>
void doulinked<T>::add(T d)
{
doulinked *n = new doulinked;
n->data=d;
if( head == NULL)
{
head = n;
tail = n;
}
else
{
head->prev = n;
n->next = head;
head = n;
}
}
template<class T>
void doulinked<T>::push_tail(T d)
{
doulinked *n = new doulinked;
n->data=d;
if( tail == NULL)
{
head = n;
tail = n;
}
else
{
tail->next = n;
n->prev = tail;
tail = n;
}
}
template <class T>
void doulinked<T>::delete_front()
{
remove(head);
}
template <class T>
void doulinked<T>::delete_back()
{
remove(tail);
}
template <class T>
void doulinked<T>::remove(doulinked* v)
{
if(v->prev!=NULL && v->next!=NULL)
{
doulinked* p = v->prev;
doulinked* n = v->next;
p->next = n;
n->prev = p;
delete v;
}
else if(v->prev==NULL && v->next!=NULL)
{
doulinked* n =v->next;
head->next = n;
n->prev = head;
delete head;
head=n;
}
else if(v->prev!=NULL && v->next==NULL) // have some wrong with this loop;
{
doulinked* p=v->prev;
p->next=tail;
tail->prev=p;
delete tail;
tail=p;
}
}
template <class T>
void doulinked<T>::remove_ele(T d) // have some wrong with this loop
{
if(head->data==d)
{
remove(head);
head=head->next;
}
else
head=head->next;
}
int main()
{
doulinked<int> dll;
dll.add(5123);
dll.add(1227);
dll.add(127);
dll.push_tail(1235);
dll.push_tail(834);
dll.push_tail(1595);
dll.delete_front();
//dll.delete_back();
//dll.remove_ele(834);
cout<<dll<<endl;
system("pause");
}
Your design is a little confused.
The traditional C++ way to design a linked list (like std::list) has separate node and list classes, instead of a single class that acts as both:
template <typename T> struct node {
node *prev, *next;
};
template <typename T> struct list {
node *head, *tail;
};
If you want to just pass around node pointers, that's fine—but then you have to pass around node pointers, not node objects. And the mutator functions have to return a pointer as well—if you call delete_front on the head node, you've now got a reference to a deleted node; you need its next or you've lost any reference to the list. Since the constructor has to return a pointer, you can't use a real public constructor; you want a static factory method instead. And so on.
You also have to be consistent about whether there's a "sentinel node" before the head (and after the tail) or not. If you're creating a sentinel in your constructor—as you are doing—new nodes inserted at the end(s) need to point at the sentinel(s)—which you aren't doing.
Also, the whole head/tail notion you're using is wrong for a node API. (Also, it's incredibly confusing to mix and match names from different styles—you've got add matching delete_front and push_tail matching delete_back…) To have a push_tail method, you either have to walk the entire list (making it O(N)), or you have to have every node hold the tail pointer (making any list change O(N)), or you have to make the head hold a tail pointer and the tail hold a head pointer.
The last one works (it wastes a couple of pointers for every node when only one node needs each, but that rarely matters). But it gets confusing to think about.
It's actually a lot simpler to just create a circular list, where the head's prev points at the tail (or sentinel) instead of 0, and the tail's next points at the head (or sentinel) instead of 0. This gets you all the advantages of a separate list class, without needing that class—if you have a pointer to the head, that's all you need to refer to the entire list (because node is the head and node->prev is the tail, or or similarly if you have a sentinel).
Also, your constructor doesn't make much sense:
doulinked()
{
head=tail=prev=next=NULL;
T data;
}
This creates a local default-constructed T variable named data, and then… does nothing with it. You probably wanted to set data to something. And you probably wanted to use initializers for this. And in that case, you don't need to do anything, because that's already the default.
And I'm not sure what Inlist is even supposed to do.
As for remove_ele(T d), presumably you want to remove the first element whose data == d, right? If you write a find method first, then it's trivial: remove(find(d)). (I'm assuming that find throws an exception; if you want find to return null or the sentinel or something else instead, and remove_ele to return true or false, obviously you need one more line to check whether the find worked.)
If you don't know how to write a find method… well, that's kind of the whole point of a linked list, there's a trivial recursive definition for all traversal functions, including find:
node *node::find(T d) {
if (data == d) { return this; }
if (next) { return next->find(d); }
return 0;
}
Anyway, I think rather than try to bang on your code until it works, you should look at existing implementations of the various designs until you understand the differences, then pick the design you want and try to implement that.

C++ boost::bind and boost::function, class member function callbacks and operator==. What am I doing wrong?

I've got a problem with using boost::bind and boost::function and passing boost::function as a callback into another class.
Here's an example that is the problematic situation:
typedef boost::function<void (bool)> callbackFunction;
class HasCallback
{
public:
HasCallback() : value(0)
{
}
int value;
void CallBackFunction(bool changed)
{
std::cout << "HasCallback class. CallBackFunction called. Parameter: " << value << std::endl;
}
};
class ReceivesCallback
{
public:
void AddCallback(callbackFunction newFunc)
{
callbacks.push_back(newFunc);
}
void execute(int &i)
{
for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
{
(*it)(i++);
}
}
void RemoveHandler(callbackFunction oldFunc)
{
for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
{
if((*it) == oldFunc)
{
callbacks.erase(it);
break;
}
}
}
private:
std::vector<callbackFunction> callbacks;
};
int main()
{
HasCallback hc;
ReceivesCallback rc;
rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc, _1));
hc.value = 123;
HasCallback hc2;
rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc2, _1));
hc2.value = 321;
int a = 0;
rc.RemoveHandler(boost::bind(&HasCallback::CallBackFunction, &hc2, _1));
rc.execute(a);
}
The problem I'm having is that this doesn't even compile. It fails within ReceivesCallback::RemoveHandler in the if((*it) == oldFunc) line with the error saying that there's more than one overload of the operator== for the thing i'm trying to do.
I keep searching for this and can't find what I'm doing wrong. Also, I keep finding contradicting information, one saying that it's possible to compare boost::function-s and another saying it's not. I can see the operator== functions within boost/function_base.hpp and i believe this is supposed to work, I just can't seem to figure out how. Can someone help me out here? My suspicion is that it fails because the parameters of the boost::bind need to be specified fully(be concrete values) but this is something i cannot get in the code I'm developing, I just need to know whether the passed handler is registered or not, since I'm binding to an object it should have all the information neeeded to make the distinction.
See Boost.Function FAQ for an explanation : Why can't I compare boost::function objects with operator== or operator!= ?.
Boost.Functions only provides comparison of a boost::function with an arbitrary function object. I believe that making your RemoveHandler member function template could fix the issue :
template<class Functor>
void RemoveHandler(const Functor &oldFunc)
{
for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
{
if((*it) == oldFunc)
{
callbacks.erase(it);
break;
}
}
}
Here, oldFunc gets to keep its actual type without being 'wrapped' in a boost::function.

Custom STL Containers

I have written code that allows one to traverse mapped data in the order it was entered.
The solution I coded a couple of times was:
Given a keytype, K, and and data type, D,
std::map
std::vector
When one wanted to randomly find a data entry, use map.find(K). When one wanted to traverse the map in entry order, use std::vector::iterator (begin(), end()].
This was fine, but as an exercise, I wanted to write this 'OrderedMap' as an STL compliant container. I also have (stripped down to this discussion):
template <typename K, typename D>
class OrderedMapValue
{
private:
K first_ref;
std::map<K,size_t>& m;
std::vector<D>& v;
public:
const K& first
D& second
assignment operator=(const D& data)
{
std::map<K,size_t>::const_iterator iter = m.find(first_ref);
v[iter.second] = data; // error checking of iter stripped
}
};
Further assuming
template <typename K, typename D>
class OrderedMap
{
public:
typename OrderedMapValue<K,D>& OrderedMap<K,D>::operator[](const K&);
// snip...
};
class MyClass
{
public:
MyClass(std::string s) : _my_data(s) {}
private:
std::string _my_data;
};
The following code works:
OrderedMap<std::string,MyClass*> omap;
omap["MyKey"] = new MyClass("dummy");
However, this code does not:
OrderedMap::iterator iter = omap.find("MyKey");
MyClass * obj = iter->second;
delete obj;
iter->second = new MyClass("dummy");
Assuming I have done something
a) Structurally silly or
b) Unnecessarily complex, how should this be done?
I realize that I'm likely reinventing the wheel here, but again, this effort is mainly to increase my knowledge of STL containers, their design patterns and proper use.
Thanks in advance for any insights,
I don't have a compiler right now to test this, so there could be errors, but I think you want it more like:
template <typename K, typename D>
class OrderedMap
{
private:
std::map<K,size_t> &m;
std::vector<D> &v;
public:
typename pair<K,D> TYPE;
TYPE& operator[](const K &k)
{
return v[ m[ k ]];
}
TYPE& operator[](size_t idx)
{
return v[ idx ];
}
pair<iterator,bool> insert( const TYPE& pair )
{
map<K, size_t>::const_iterator iter;
iter = m.find( pair.first );
if( iter != m.end() )
return make_pair( v[ iter.second], false );
m.insert( make_pair( pair->first, v.size() ));
v.push_back( pair->second );
return make_pair( v.last() , inserted );
}
iterator &begin()
{
return v.begin();
}
// etc
};
In OrderedMapValue::operator=, you have:
std::map<K,size_t>::const_iterator iter = m.find(first_ref);
What is first_ref? The code doesn't reference it (no pun intended) elsewhere. It looks to me like it might be a vestige from an older implementation, replaced elsewhere by the public member
const K& first.
Could this be the problem?
EDIT from the comments: The code doesn't show that first_ref is initialized anywhere; so for all I can tell, the call to m.find(first_ref) is searching for an empty string, rather than the key for the OrderedMapValue.