Pavel
Can you provide the code. From what you explained it seems that the problem may be that the implementation of the templated class should be in hpp. But without looking at the code it is just a wild guess.
Pavel
I was answering to another message, sorry for the confusion
Anonymous
https://gist.github.com/4a73bcdd3a6bbf6c3790ff7529e0c069 how do i handle undoing a FIFO full add? eg 123 > 234 > 345 > undo > 234 > undo > 123 size == 3 stack {1,2,3,4,5} size == 5 front == 1, back == 5
Pavel
First of all it looks incorrect that your implementations are in cpp, but not sure if it's the case of the problem in this situation (it should be a linker error, I guess, in that case). Does the error point to a specific line of the code?
Pavel
Templated functions/classes are generated for each type (combination of types) they were instantiated with. Basically if you use std::vector<int> and std::vector<float> in your app, you will have two generated usual classes. But in order to generate them for each type, both the type and the implementation code should be visible in one place. One way: you can put your implementation to hpp, then when the compiler will meet the place when it's instantiated, e.g. std::vector<int> myVector; it will be able to generate the implementation for this specific type. Another way, you can add full specializations of your template to the cpp for specific types. Then linker will make sure to link callers to these specializations.
Pavel
I think so, I mean about visibility in one place I pretty sure it works always. You can put the implementation code somewhere where it visible for the called and it will work. Usually if it's just a template or partial specialization you just put it to the header. If it's full specialization you put it in cpp (treating it just as a usual function)
Thierry
thank you for your assistance and help @gameraccoon
Pavel
About this I'm not sure, my phone battery is almost dead, I'll have a look later if no one else will be able to help before that
Igor🇺🇦
Why do you have templates twice on line 33 and 34? Shouldn't it be only one line?
Anonymous
Hi
Ehsan
so what’s the implementation you want to do?
Anonymous
this depends on how do you want to implement the undo, redo.
i would like to be able to undo the add/push operation fully, in the event where the push results in the last value being erased
Anonymous
eg 123 > push(4) > 234 > undo() > 123
Ehsan
what is the one you decided to do?
Ehsan
we can save instants of the stack
Anonymous
at the moment i just keep all values in a ring buffer
Anonymous
eg for a full buffer: add 3 MAIN: (size = 3, capacity = 3) 1, 2, 3 UNDO: (size = 6, capacity = 6) { ADD, 1 }, { ADD, 2 }, { ADD, 3 } overwrite the buffer by pushing another value, causing the last value to be removed add 4 MAIN: (size = 3, capacity = 3) 2, 3, 4 UNDO: (size = 6, capacity = 6) { ADD, 2 }, { ADD, 3 }, { ADD, 4 }
Ehsan
at the moment i just keep all values in a ring buffer
and if the stack got full what do you do?
Anonymous
Anonymous
for example, this is with a main buffer of 3 and a undo buffer of 4 (* 2 for commands) add 3 MAIN: (size = 3, capacity = 3) 1, 2, 3 UNDO: (size = 6, capacity = 8 ) { ADD, 1 }, { ADD, 2 }, { ADD, 3 }, _ add 4 MAIN: (size = 3, capacity = 3) 2, 3, 4 UNDO: (size = 8, capacity = 8 ) { ADD, 1 }, { ADD, 2 }, { ADD, 3 }, { ADD, 4 }
Igor🇺🇦
the user can choose a custom capacity for each buffer
So you'll not restore data from capacity+1 steps back?
Anonymous
So you'll not restore data from capacity+1 steps back?
the buffer size of the undo is just how many operations it is capable of undoing
Anonymous
eg it could undo up to 10 uperations, or up to 50 operations, or just up to 4 operations while the main buffer may only hold say 2 values max, or 20 values max or even just 1 value max
Ehsan
ok so it’s very easy actually, all you need to do is reverse the command 🙂 if a queue is full you can make an array that holds the numbers that got deleted
Ehsan
it’s so simple
Anonymous
the main importance here is that i do not allocate memory to store the history
Ehsan
the main importance here is that i do not allocate memory to store the history
impossible 🙂 you need to store the value to retrive it later
Anonymous
ok so it’s very easy actually, all you need to do is reverse the command 🙂 if a queue is full you can make an array that holds the numbers that got deleted
like, if say this? UNDO: 1, 2, 3 EXTENDED_UNDO: _, _, _ add 8 UNDO: 2, 3, 8 EXTENDED_UNDO: 1, _, _ add 16 UNDO: 3, 8, 16 EXTENDED_UNDO: 1, 16, _
Ehsan
unless you have a big queue, let’s say 60, 10 for history 50 for entries
Ehsan
then you can implement
Ehsan
like, if say this? UNDO: 1, 2, 3 EXTENDED_UNDO: _, _, _ add 8 UNDO: 2, 3, 8 EXTENDED_UNDO: 1, _, _ add 16 UNDO: 3, 8, 16 EXTENDED_UNDO: 1, 16, _
add 1 2 3 1 2 3 add 8 stack push 81 in the undo buff 8 2 3 back = 0 forward = 1 undo back = 2 forward = 0 pop the 1 and add it 1 2 3
Ehsan
easy
Ehsan
you can always use the back to assign the value 🙂 because it’s cirular
Igor🇺🇦
the main importance here is that i do not allocate memory to store the history
Why can't you use linked list and and index to the beginning of the main buffer?
Ehsan
if stack is not empty: queue(back++) = pop(stack) forward— else back—
Anonymous
add 1 2 3 1 2 3 add 8 stack push 81 in the undo buff 8 2 3 back = 0 forward = 1 undo back = 2 forward = 0 pop the 1 and add it 1 2 3
im not sure i understand that, as the data is represented in its internal format instead of its human readable format
Anonymous
eg this->next = new History(val) ?
Ehsan
add 1 2 3 1 2 3 add 8 stack push 81 in the undo buff 8 2 3 back = 0 forward = 1 undo back = 2 forward = 0 pop the 1 and add it 1 2 3
here wanted to add 8, but it’s full(1 2 3): since it’s full we will add queue(forward) to the undo buff stack (which is 1 here) and put 8 8 2 3
Ehsan
if stack is not empty: queue(back++) = pop(stack) forward— else back—
now use this algorithm and the undo will be succeful
Anonymous
if stack is not empty: queue(back++) = pop(stack) forward— else back—
which is what i already do push_front(redo_, command.cmd, pop_back(main));
Anonymous
to undo an add
Igor🇺🇦
Ehsan
to undo an add
yes this is how you undo an add
Ehsan
if you want to undo a remove it’s also as simple
Anonymous
and push_front(main, push_front(redo_, command.cmd, pop_back(main)).data); to undo a remove (though i have not tested undoing a remove yet)
Ehsan
you don’t need linked list since the buff capacity is determined
Ehsan
all you need is to reverse a command
Anonymous
@neko_code any java group, connect please??
Anonymous
ok so what’s the problem?
the problem, is undoing an add that causes the buffer to wrap around
Ehsan
this is how you reverse add
ofcourse you need to add conditions when queue is empty and if buff capacity was exceded etc
Anonymous
specifically with MAIN: (size = 3, capacity = 3) 3, 4, 5 UNDO: (size = 10, capacity = 12) { ADD, 1 }, { ADD, 2 }, { ADD, 3 }, { ADD, 4 }, { ADD, 5 }, _
Anonymous
as front would be 1 and back would be 5 but i need to obtain 2
Ehsan
as front would be 1 and back would be 5 but i need to obtain 2
add 1 2 3 123 add 4 push 1 4 23 add 5 push 2 4 5 3 undo pop 2 4 2 3 undo pop 1 1 2 3
Ehsan
it’s working 🙂
Anonymous
like the only option i see would be to rebuild the queue, removing the value at the computed index that i need
Ehsan
you can implement two queues one for the MAIN and one for the UNDO
Ehsan
okay so?
Ehsan
what’s the problem? I don’t see any problem?
Anonymous
mine works like this push 1, push 6 MAIN: (size = 2, capacity = 3) 1, 6, _ UNDO: (size = 0, capacity = 6) _, _, _ front = 1, back = 6 pop back (remove 6, or 1 if pop front instead) MAIN: (size = 1, capacity = 3) 1, _, _ UNDO: (size = 0, capacity = 6) _, _, _
Ehsan
nein nein, you use a queue here, you don’t pop the six
Ehsan
you just move ther back to the left
Ehsan
back—
Ehsan
you don’t even need to store the one because all you need to do is: back—