- What is the correct template type? - 4 Updates
- Deriving an iterator - 9 Updates
- cancel <cg8q28F5ftnU1@mid.individual.net> - 1 Update
- Deriving from an iterator - 1 Update
- ++++i; - 1 Update
JiiPee <no@notvalid.com>: Dec 27 10:36PM I am trying to make xx (in pair2_derived) to be a reference member variable so that it refers to "first" in pair2. What should I put as a type for xx? I first tried T (because it is/will be the type in real life), but I get "error: expected ';' at end of member declaration". I tried other ones as well like pair2<T, T>::_T1 but none worked. I am not very familiar with templates so would need some help here, thanks. template<class _T1, class _T2> struct pair2 { _T1 first; _T2 second; }; template <typename T> class pair2_derived: public pair2<T, T> { public: T& xx = pair2<T, T>::first; // xx has a wrong type...what should the type of xx be? }; --- This email has been checked for viruses by Avast antivirus software. http://www.avast.com |
Paavo Helde <myfirstname@osa.pri.ee>: Dec 27 05:17PM -0600 > type for xx? I first tried T (because it is/will be the type in real > life), but I get "error: expected ';' at end of member declaration". I > tried other ones as well like pair2<T, T>::_T1 but none worked. I am not > _T1 first; > _T2 second; > }; Identifiers like _T1 are reserved for implementations, it is illegal to use them in your own code. > { > public: > T& xx = pair2<T, T>::first; // xx has a wrong type...what should the > type of xx be? > }; template <typename T> class pair2_derived: public pair2<T, T> { public: T& xx; pair2_derived(): xx(this->first) {} }; |
JiiPee <no@notvalid.com>: Dec 27 11:33PM On 27/12/2014 23:17, Paavo Helde wrote: >> }; > Identifiers like _T1 are reserved for implementations, it is illegal to > use them in your own code. Ok, but that does not seem to be the problem here. Even if I take _ off from it for example pair2<T, T>::T1& xx = pair2<T, T>::first; does not work. |
"Öö Tiib" <ootiib@hot.ee>: Dec 27 03:34PM -0800 On Sunday, December 28, 2014 12:36:18 AM UTC+2, JiiPee wrote: > T& xx = pair2<T, T>::first; // xx has a wrong type...what should the > type of xx be? > }; No compiler nearby but it might be that this works like you want: template <typename T> class pair2_derived: public pair2<T, T> { public: typedef pair2<T, T> base; T& xx = base::first; }; int main() { pair2_derived<int> x; x.first = 42; x.second = 43; std::cout << "xx is:" << x.xx << std::endl; return 0; } |
jononanon@googlemail.com: Dec 27 09:57AM -0800 Hi there, I've derived std::vector and std::vector::iterator . Unfortunately the derived iterator does not work as I would like. ///// test.cpp ////////////////////////////////////////////////// #include <iostream> #include <vector> using std::vector; template<typename T> struct Myvec : public vector<T> { using vector<T>::vector; class myiterator; myiterator begin1() {return myiterator{static_cast<vector<T>>(*this).begin()}; } myiterator end1() {return myiterator{static_cast<vector<T>>(*this).end()}; } const myiterator begin1()const {return myiterator{static_cast<vector<T>>(*this).begin()}; } const myiterator end1() const {return myiterator{static_cast<vector<T>>(*this).end()}; } }; template<typename T> struct Myvec<T>::myiterator : public vector<T>::iterator{ // CONSTRUCTOR myiterator(const typename vector<T>::iterator& it) : vector<T>::iterator{it} {} using vector<T>::iterator::iterator; }; int main() { Myvec<int> vec = {1, 2, 3}; for (Myvec<int>::myiterator it = vec.begin1(); it != vec.end1(); ++it) { std::cout << *it << '\n'; } return 0; } /////////////////////////////////////////////////////// Compile (on linux) with c++ -std=c++11 -o test test.cpp EXPECTED ("wanted") OUTPUT: 1 2 3 The OUTPUT I unfortunately get: 0 0 3 What's wrong with the code? How does one get it working so that the derived iterator is usable (in the way I want) Thanks. |
jononanon@googlemail.com: Dec 27 10:17AM -0800 OK, here's how to SOLVE it: Instead of static_cast<vector<T>>(*this).begin() USE THIS: static_cast<vector<T>*>(this)->begin() But the more important question: why does only the 2nd one work correctly??? Thanks for any help and pointers ;) on this!! J. Below is the full code: /////////////////////////////////////////////////////// #include <iostream> #include <vector> using std::vector; template<typename T> struct Myvec : public vector<T> { using vector<T>::vector; class myiterator; myiterator begin1() {return myiterator{static_cast<vector<T>*>(this)->begin()}; } myiterator end1() {return myiterator{static_cast<vector<T>*>(this)->end()}; } const myiterator begin1()const {return myiterator{static_cast<vector<T>*>(this)->begin()}; } const myiterator end1() const {return myiterator{static_cast<vector<T>*>(this)->end()}; } }; template<typename T> struct Myvec<T>::myiterator : public vector<T>::iterator{ // CONSTRUCTOR myiterator(const typename vector<T>::iterator& it) : vector<T>::iterator{it} {} using vector<T>::iterator::iterator; }; int main() { Myvec<int> vec = {1, 2, 3}; for (Myvec<int>::myiterator it = vec.begin1(); it != vec.end1(); ++it) { std::cout << *it << '\n'; } return 0; } /////////////////////////////////////////////////////// |
Victor Bazarov <v.bazarov@comcast.invalid>: Dec 27 03:10PM -0500 > But the more important question: why does only the 2nd one work correctly??? > Thanks for any help and pointers ;) on this!! > J. The first expression creates a temporary vector<T>, which disappears as soon as the full expression has been evaluated. The second expression does not create a temporary and instead yields an iterator for the existing ('this') vector. The second one works correctly most likely because you actually need the iterator for the existing vector and not for some temporary (which becomes invalid as soon as the temporary is destroyed, BTW). V -- I do not respond to top-posted replies, please don't ask |
Paavo Helde <myfirstname@osa.pri.ee>: Dec 27 03:19PM -0600 jononanon@googlemail.com wrote in > static_cast<vector<T>*>(this)->begin() > But the more important question: why does only the 2nd one work > correctly??? As Victor explained, the first one makes a copy. To avoid the copy, one can also cast to a reference: static_cast<vector<T>&>(*this).begin() That said, std::vector (and other STL containers) are not really meant for derivation. If you want to build on top of them, use them as data members, not as bases. This will work out better in long term (short rationale: public derivation leaks out the inner guts of std::vector, which will overcomplicate your class' interface and make it hard to maintain its class invariants). Cheers Paavo |
jononanon@googlemail.com: Dec 27 01:21PM -0800 On Saturday, December 27, 2014 9:10:41 PM UTC+1, Victor Bazarov wrote: > because you actually need the iterator for the existing vector and not > for some temporary (which becomes invalid as soon as the temporary is > destroyed, BTW). Oh yes, I think you're right! The first version.... static_cast<vector<T>>(*this) goes ahead and actually USES A COPY CONSTRUCTOR to create a temporary copy of the vector; and then calls begin() to return an iterator for this temporary. Definitely not what I wanted. I need an iterator to the initial vector, therefore using a pointer and deref via -> is what is needed. |
jononanon@googlemail.com: Dec 27 01:28PM -0800 On Saturday, December 27, 2014 10:19:29 PM UTC+1, Paavo Helde wrote: > static_cast<vector<T>&>(*this).begin() Ah yes, thank! > rationale: public derivation leaks out the inner guts of std::vector, > which will overcomplicate your class' interface and make it hard to > maintain its class invariants). This makes sense. Because as it happens, I'm working with a derived vector, that handles pointers and automatically deletes them in the destructor. And "SURPRISE": I have to also overload 'erase' to also do deletes! And other stuff as well... probably. Which is exactly what you say in the rationale. Thanks. |
"Jens Müller" <ich@tessarakt.de>: Dec 27 11:27PM +0100 > Because as it happens, I'm working with a derived vector, that handles pointers and automatically deletes them in the destructor. And "SURPRISE": I have to also overload 'erase' to also do deletes! And other stuff as well... probably. Which is exactly what you say in the rationale. Then a better solution is probably to use a normal std::vector and put suitable smart pointers (e.g. std::unique_ptr) into it. |
jononanon@googlemail.com: Dec 27 03:05PM -0800 On Saturday, December 27, 2014 11:27:32 PM UTC+1, Jens Müller wrote: > > Because as it happens, I'm working with a derived vector, that handles pointers and automatically deletes them in the destructor. And "SURPRISE": I have to also overload 'erase' to also do deletes! And other stuff as well... probably. Which is exactly what you say in the rationale. > Then a better solution is probably to use a normal std::vector and put > suitable smart pointers (e.g. std::unique_ptr) into it. Challange: try that suggestion of yours using std::unique_ptr ;) Here's a solution (no peeking!): /////////////////////////////////////// #include <vector> #include <memory> #include <initializer_list> using std::vector; template<typename T> struct pvector : public vector<std::unique_ptr<T>>{ // using vector<std::unique_ptr<T>>::vector; pvector(std::initializer_list<T*> lst); void push_back(T *p) { static_cast<vector<std::unique_ptr<T>> *>(this)->push_back(std::unique_ptr<T>{p}); } }; template<typename T> pvector<T>::pvector(std::initializer_list<T*> lst) { for (T* p: lst) { push_back(p); } } /////////////////////////////////////// Yip, what makes this interesting is the fact that std::unique_ptr cannot be copied (in order to prevent double frees!) |
Paavo Helde <myfirstname@osa.pri.ee>: Dec 27 05:11PM -0600 jononanon@googlemail.com wrote in > using std::vector; > template<typename T> > struct pvector : public vector<std::unique_ptr<T>>{ I think you did not get the idea, which was to just use std::vector of a suitable element type, not to derive from it. typedef vector<std::unique_ptr<mytype>> pvector; If std::unique_ptr does not work for you by some reason, consider std::shared_ptr. Cheers Paavo |
ich@tessarakt.de: Dec 27 10:28PM This message was cancelled from within Mozilla Thunderbird. |
jononanon@googlemail.com: Dec 27 10:01AM -0800 Hi there, Im deriving from std::vector and std::vector::iterator. /////////// test.cpp /////////////////////////////// #include <iostream> #include <vector> using std::vector; template<typename T> struct Myvec : public vector<T> { using vector<T>::vector; class myiterator; myiterator begin1() {return myiterator{static_cast<vector<T>>(*this).begin()}; } myiterator end1() {return myiterator{static_cast<vector<T>>(*this).end()}; } const myiterator begin1()const {return myiterator{static_cast<vector<T>>(*this).begin()}; } const myiterator end1() const {return myiterator{static_cast<vector<T>>(*this).end()}; } }; template<typename T> struct Myvec<T>::myiterator : public vector<T>::iterator{ // CONSTRUCTOR myiterator(const typename vector<T>::iterator& it) : vector<T>::iterator{it} {} using vector<T>::iterator::iterator; }; int main() { Myvec<int> vec = {1, 2, 3}; for (Myvec<int>::myiterator it = vec.begin1(); it != vec.end1(); ++it) { std::cout << *it << '\n'; } return 0; } /////////////////////////////////////////////// Compile (on linux) with: c++ -std=c++11 -o test test.cpp EXPECTED OUTPUT: 1 2 3 REAL OUTPUT is unfortunately: 0 0 3 How can one fix the code? How does one properly derive an iterator and get it working? Thanks. |
Jack Chuge <zhuge.jack@gmail.com>: Dec 27 07:54PM +0800 Martijn Lievaart 於 2014-12-4 3:47 寫道: >> be in live code. > Yeah, ++++i feels like some other unspecified computer language. :-) > M4 Martin, I agree with you, lol -- Jack |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment