Thank you very much, Prof Mike Shah Ph.D (Tufts) This presentation is Bjarne like I love C++. It is no magic. Let’s be expecting a reference textbook on Modern Cpp from you in the future Stay fine and keep updating us.
You make very good videos covering beginner level and deep dive to expert level. I know in long run your videos gonna be hit, keep up the good work. God bless you :)
Thank you for this helpful video! Just one note: the postfix increment operator must have (int) argument not the actual type. That should be: // it++ iterator operator++(int){ ....
I just watched this video again and attempt it on a custom LinkedList. What I found really helpful about this video is how you showed using the compiler errors to step by step implement the iterator. I found the following to be really helpful to see what each of the components are doing: LinkedList ll{}; LinkedList::iterator begin = ll.begin(); LinkedList::iterator end = ll.end(); std::cout
Absolutely engaging content! Your video was both highly informative and applicable. I really appreciate this style of teaching where we get to dig deep into the code and see how things work from the ground up. Each time you were about to begin implementation, I paused the video and attempted to code on my own. Afterward, I compared my work with your solution. This interactive learning experience was incredibly beneficial for me. Thank you ever so much for your valuable contribution to my learning journey in C++ development.
The compiler always optimizes unused post inc however it is good practice to not rely on optimizations [ntm actually communicate the algorithm you want].
Agreed -- best to explicitly tell the compiler exactly what to do in case the optimizations do not hold. Also, when debugging and optimization does not take place, you are debugging closer to the actual behavior 🙂
why don't you write the struct iterator out of the class FixedSizeArray? As template struct iterator { ... }; template class FixedSizeArray { ... }; passing the instance of FixedSizeArray as an additional parameter to the struct iterator's constructor.
If I was going to use this same type of iterator for other classes, indeed it would be better to define it outside the class, and potentially provide it as a 'strategy' (through template argument as you suggested) to each instance of a class :)
So a few thoughts on this: 1.) With 'friend' functions it acts as if it was indeed a member function (i.e. you get access to private/protected members) 2.) The advantage of a 'friend' function is you get a little more control of the parameters. i.e., You have both parameters that you can control. So if there is some cast for one or both of the parameters, you can do the comparison. With the member function, you are effectively always comparing with the 'this' object of the specific type, so you could have a mismatch, or perhaps other strange behavior. 3.) Also don't forget, if you don't truly need private access for friend function, you can make it a non-friend function for the operator== (..., ...) function.
l was doing the same thing recently, but I tried to make custom exception classes for dynamic array iterator. For example, if pointer field in iterator points in wrong adress, which is not belonged to array's values, the iterator throws exception and calles std::abort(). But I have no idea how to do this, because it requires acsess to array objects' private fields from namespace of iterator class. I tried to implement acsess through temlplate arguments: template class iterator{}; I was failed, because template arguments must be with constexpr specifier. Do you have any ideas? if so, I would very pleased if you give me some hints about this stuff.
Hmm, that's an interesting idea to try to setup the iterator with template arguments. Briefly I looked at Safe Iterators here: stlplus.sourceforge.net/stlplus3/docs/safe_iterator.html The easy thing to do is have an iterator specifc to each type that could otherwise 'peek' into the object, and otherwise know about the 'pair' iterator (when a range is used) so that you would otherwise know if you're pointing to the same object. If the object changes its internal allocation, then it's possible to update the iterators as well. I think with ranges (and std::ranges) in C++, in this way it becomes a lot harder to have iterator invalidation with a different pair of iterators -- and depending on how the range is implemented, perhaps iterator invalidation is also more difficult?
@@MikeShahthank you for your feedback! I solved my problem with acsess to array objects' private fields: I just added pointer to array object as private field in iterator class. It still doesn't update iterator pointing adress after changing array's internal allocation, but I'm satisfied with the fact that I secured users from segmentatation fault.
@@user-eh8jh4cd2t I suppose you could store a reference to the array that it points to, and just have a flag or something for that class if it calls 'capacity' function. If you own the class you can certainly do that. If you're trying to do that with the STL types (e.g. std::vector), I'll need to think about that a little more on how to either do 'compile-time interpositioning' and override the default behavior of capacity, or some other strategy perhaps.
should iterator structs be declared private? I seem to get an error with a custom iterator attempt of mine, when the structs are declared private (versus public, which does seem possibly problematic but seems to work (read: compiles))
Thank you very much, Prof Mike Shah Ph.D (Tufts)
This presentation is Bjarne like
I love C++. It is no magic.
Let’s be expecting a reference textbook on Modern Cpp from you in the future
Stay fine and keep updating us.
Cheers, thanks for the kind words Joe!
I love these deep dives into how certain features work or are implemented. I really enjoyed the Observables series a while back!
Cheers, thank you for the kind words!
You make very good videos covering beginner level and deep dive to expert level.
I know in long run your videos gonna be hit, keep up the good work.
God bless you :)
Cheers! Thank you for the kind words
Thank you for this helpful video!
Just one note: the postfix increment operator must have (int) argument not the actual type.
That should be:
// it++
iterator operator++(int){
....
Cheers!
Thank you very much for this video. Helped me out a lot !!
Cheers, happy to hear that!
Thank you so much for this. If you didn't explain this, I don't think I would have had any hope of understanding it.
Cheers -- always happy to help Damon!
I just watched this video again and attempt it on a custom LinkedList. What I found really helpful about this video is how you showed using the compiler errors to step by step implement the iterator. I found the following to be really helpful to see what each of the components are doing:
LinkedList ll{};
LinkedList::iterator begin = ll.begin();
LinkedList::iterator end = ll.end();
std::cout
Awesome, well done! @@damondouglas
Absolutely engaging content! Your video was both highly informative and applicable. I really appreciate this style of teaching where we get to dig deep into the code and see how things work from the ground up.
Each time you were about to begin implementation, I paused the video and attempted to code on my own. Afterward, I compared my work with your solution. This interactive learning experience was incredibly beneficial for me. Thank you ever so much for your valuable contribution to my learning journey in C++ development.
Cheers, you are most welcome as always Sam!
The compiler always optimizes unused post inc however it is good practice to not rely on optimizations [ntm actually communicate the algorithm you want].
Agreed -- best to explicitly tell the compiler exactly what to do in case the optimizations do not hold. Also, when debugging and optimization does not take place, you are debugging closer to the actual behavior 🙂
Thank you very much for the video! Was a lean itteration(wink wink) from basic to more complex stuff. You have a real talent for teaching😊
Thank you for the kind words!
why don't you write the struct iterator out of the class FixedSizeArray? As
template
struct iterator { ... };
template
class FixedSizeArray { ... };
passing the instance of FixedSizeArray as an additional parameter to the struct iterator's constructor.
If I was going to use this same type of iterator for other classes, indeed it would be better to define it outside the class, and potentially provide it as a 'strategy' (through template argument as you suggested) to each instance of a class :)
Looking at 33:11, is this a good use case for the spaceship operator? Could you make a video on the spaceship operator anyway?
Potentially yes -- spaceship operator video will be on the playlist, it's in the queue to show up here eventually :)
amazing content sent!!!
Cheers!
Really nice tuto. Still I would like to ask you why we need to specify the bool operator== as friend this I really don't get
So a few thoughts on this:
1.) With 'friend' functions it acts as if it was indeed a member function (i.e. you get access to private/protected members)
2.) The advantage of a 'friend' function is you get a little more control of the parameters. i.e., You have both parameters that you can control. So if there is some cast for one or both of the parameters, you can do the comparison. With the member function, you are effectively always comparing with the 'this' object of the specific type, so you could have a mismatch, or perhaps other strange behavior.
3.) Also don't forget, if you don't truly need private access for friend function, you can make it a non-friend function for the operator== (..., ...) function.
Great video! Thank you!
Do you have any video's that run through assigning functions or constructors with either default or delete keywords?
Cheers! In my list of videos, I believe I actually do not! courses.mshah.io/pages/RUclipsLibrary I will have to revisit that at some point
Thanks a lot for this great video.
Cheers, you are most welcome!
l was doing the same thing recently, but I tried to make custom exception classes for dynamic array iterator. For example, if pointer field in iterator points in wrong adress, which is not belonged to array's values, the iterator throws exception and calles std::abort().
But I have no idea how to do this, because it requires acsess to array objects' private fields from namespace of iterator class.
I tried to implement acsess through temlplate arguments:
template class iterator{};
I was failed, because template arguments must be with constexpr specifier.
Do you have any ideas? if so, I would very pleased if you give me some hints about this stuff.
Hmm, that's an interesting idea to try to setup the iterator with template arguments.
Briefly I looked at Safe Iterators here: stlplus.sourceforge.net/stlplus3/docs/safe_iterator.html
The easy thing to do is have an iterator specifc to each type that could otherwise 'peek' into the object, and otherwise know about the 'pair' iterator (when a range is used) so that you would otherwise know if you're pointing to the same object. If the object changes its internal allocation, then it's possible to update the iterators as well. I think with ranges (and std::ranges) in C++, in this way it becomes a lot harder to have iterator invalidation with a different pair of iterators -- and depending on how the range is implemented, perhaps iterator invalidation is also more difficult?
@@MikeShahthank you for your feedback! I solved my problem with acsess to array objects' private fields: I just added pointer to array object as private field in iterator class.
It still doesn't update iterator pointing adress after changing array's internal allocation, but I'm satisfied with the fact that I secured users from segmentatation fault.
@@user-eh8jh4cd2t I suppose you could store a reference to the array that it points to, and just have a flag or something for that class if it calls 'capacity' function. If you own the class you can certainly do that. If you're trying to do that with the STL types (e.g. std::vector), I'll need to think about that a little more on how to either do 'compile-time interpositioning' and override the default behavior of capacity, or some other strategy perhaps.
should iterator structs be declared private? I seem to get an error with a custom iterator attempt of mine, when the structs are declared private (versus public, which does seem possibly problematic but seems to work (read: compiles))
I don't think it should matter as the only difference with struct and class is the default access.
You should use operator++(int) for postfix increment operator. Using anything else than "int" as an ignored argument is uncommon.
Noted!
Great video
Cheers, thank you for the kind words!