/* 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.
Related
I would like to express something like this in Critcl:
void setter(int* grid, int value, int x, int y) {
grid[xy2addr(x,y)] = value;
}
I'm in particular stuck on how to deal with int* grid in Critcl. object? bytes? Custom type maybe?
Related to this question.
This case doesn't map very well onto Tcl's value model. The issue is that grid is (a pointer to) an updateable value collection. There are two ways of modelling this in Tcl in general:
As an opaque object.
As a variable containing a Tcl list (since in model terms, while Tcl values are thought of as immutable, Tcl variables are mutable).
I'll describe how to do both below, but I'm guessing that you're going to be thinking of these zOrder things as a distinct mutable type and that the additional modest one-time overhead of making the custom type will suit you far better.
Opaque (Mutable) Objects
When working with opaque objects, you pass handles to them (basically just a name) around and then you unpack them as a custom Critcl type. The trick is to create some helper functions in C to do the mapping (this can be in a critcl::ccode command) that does the mapping between names and pointers. This is slightly messy to do, but is just about building a couple of hash tables.
critcl::ccode {
static Tcl_HashTable *zOrderMap = NULL, *zOrderRevMap = NULL;
static Tcl_Obj *
MakeZOrderObj(int *zOrder) {
/* Initialize the two maps, if needed */
if (zOrderMap == NULL) {
zOrderMap = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitObjHashTable(zOrderMap);
zOrderRevMap = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(zOrderRevMap, TCL_ONE_WORD_KEYS);
}
int isNew;
Tcl_HashEntry *hPtr = Tcl_FindHashEntry(zOrderRevMap, (char*) zOrder, &isNew);
if (!isNew) {
return Tcl_GetHashValue(hPtr);
}
/* make a handle! */
Tcl_Obj *handle = Tcl_ObjPrintf("zOrder%ld", (long) zOrder);
Tcl_SetHashValue(hPtr, handle);
Tcl_IncrRefCount(handle);
hPtr = Tcl_CreateHashEntry(zOrderMap, (char*) handle, &isNew);
Tcl_SetHashValue(hPtr, zOrder);
return handle;
}
static int
GetZOrderFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int **zOrderPtr) {
Tcl_HashTable *hPtr;
if (!zOrderMap || (hPtr = Tcl_FindHashEntry(zOrderMap, (char *) objPtr)) == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("no such zOrder \"%s\"",
Tcl_GetString(objPtr)));
return TCL_ERROR;
}
*zOrderPtr = (int *) Tcl_GetHashValue(hPtr);
return TCL_OK;
}
}
With that helper code in place, you can then define a custom Critcl type like this:
critcl::argtype zOrder {
if (GetZOrderFromObj(interp, ##, #A) != TCL_OK) {
return TCL_ERROR;
}
} int*
critcl::resulttype zOrder {
if (rv == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, MakeZOrderObj(rv));
return TCL_OK;
} int*
That then lets you write your real code as something like this. Note that grid is defined as being of (custom) type zOrder, and that those can only be manufactured by some code that returns a zOrder as its result.
critcl::cproc setter {zOrder grid int value int x int y} void {
grid[xy2addr(x,y)] = value;
}
(The deletion function that removes the entries from the hash tables and deletes the C array is left as an exercise.)
Tcl List Variable
The other way of doing this is to make zOrder values be held in Tcl variables as lists of integers. This can be nice because it lets you look inside easily, but it can also be not so nice in other ways, as the code is not constrained to work with proper values and you expose your cprocs to more details of what's happening in Tcl.
critcl::cproc setter {Tcl_Interp* interp object varName int value int x int y} ok {
/* Unpack the list of ints from the variable */
Tcl_Obj *listObj = Tcl_ObjGetVar2(interp, varName, NULL, TCL_LEAVE_ERR_MSG);
if (listObj == NULL)
return TCL_ERROR;
Tcl_Obj **listv; int listc;
if (Tcl_ListObjGetElements(interp, listObj, &listc, &listv) != TCL_OK)
return TCL_ERROR;
int *grid = alloca(sizeof(int) * listc);
for (int i=0; i<listc; i++)
if (Tcl_GetIntFromObj(interp, listv[i], &grid[i]) != TCL_OK)
return TCL_ERROR;
/* The core of the functionality */
grid[xy2addr(x,y)] = value;
/* Repack the list of ints from the variable; this code could be optimized in this case! */
for (int i=0; i<listc; i++)
listv[i] = Tcl_NewIntObj(grid[i]);
listObj = Tcl_NewListObj(listc, listv);
Tcl_ObjSetVar2(interp, varName, NULL, listObj, 0);
return TCL_OK;
}
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.
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.
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.
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.