|
From: Phil Bouchard on 20 Jun 2008 04:46 Greetings, I am wondering what would be the best way to instanciate an STL container with a special allocator but using a smart pointer to access the nodes. Apart from this the allocator will generate dictinct pointee type named "smart<>". For example: template <typename T> smart { T e_; ...}; template <typename T> smart_ptr { T * p_; ... smart_ptr(smart<T> *) {...} }; template <typename T> smart_allocator { typedef size_t size_type; typedef ptrdiff_t difference_type; typedef smart <T> * pointer; typedef const smart <T> * const_pointer; typedef smart <T> & reference; typedef const smart <T> & const_reference; typedef smart <T> value_type; ... }; int main() { std::vector < int, smart_allocator<int> > cInt; } Now I would like all nodes allocated by smart_allocator to be referenced by a smart_ptr but I think this is not possible because raw pointers is hard coded into STL which is very strange. I therefore don't use them, just pointers to smart<> (smart<> *) but when I attempt to compile such code I run into problems compiling "__normal_iterator". But I am wondering why is that class related to my allocator at all? I would like some enlightenment regarding this: ....stl_vector.h: In member function `__gnu_cxx::__normal_iterator<typename _Alloc::const_pointer, std::vector<_Tp, _Alloc> > std::vector<_Tp, _Alloc>::begin() const [with _Tp = int, _Alloc = smart_allocator<int>]': ....stl_vector.h:221: instantiated from `std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = int, _Alloc = smart_allocator<int>]' shifted_ptr_test2.cpp:66: instantiated from here ....stl_vector.h:322: error: no matching function for call to `__gnu_cxx::__normal_iterator<const smart<int>*, std::vector<int, smart_allocator<int> > >::__normal_iterator(int* const&)' ....stl_iterator.h:587: note: candidates are: __gnu_cxx::__normal_iterator<const smart<int>*, std::vector<int, smart_allocator<int> > >::__normal_iterator(const __gnu_cxx::__normal_iterator<const smart<int>*, std::vector<int, smart_allocator<int> > >&) ....stl_iterator.h:603: note: __gnu_cxx::__normal_iterator<_Iterator,_Container>::__normal_iterator(const _Iterator&) [with _Iterator = const smart<int>*, _Container = std::vector<int, smart_allocator<int> >] ....stl_iterator.h:600: note: __gnu_cxx::__normal_iterator<_Iterator,_Container>::__normal_iterator() [with _Iterator = const smart<int>*, _Container = std::vector<int, smart_allocator<int> >] Regards, -Phil -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Kai-Uwe Bux on 20 Jun 2008 12:53 Phil Bouchard wrote: > Greetings, > > I am wondering what would be the best way to instanciate an STL container > with a special allocator but using a smart pointer to access the nodes. > Apart from this the allocator will generate dictinct pointee type named > "smart<>". For example: > > template <typename T> > smart > { T e_; ...}; > > template <typename T> > smart_ptr > { > T * p_; > ... > smart_ptr(smart<T> *) {...} > }; > > template <typename T> > smart_allocator > { > typedef size_t size_type; > typedef ptrdiff_t difference_type; > typedef smart <T> * pointer; > typedef const smart <T> * const_pointer; > typedef smart <T> & reference; > typedef const smart <T> & const_reference; > typedef smart <T> value_type; > ... > }; Your allocator violates [20.1.5/4] Implementations of containers described in this International Standard are permitted to assume that their Allocator template parameter meets the following two additional requirements beyond those in Table 32. [...] ? The typedef members pointer, const_pointer, size_type, and difference_type are required to be T*,T const*, size_t, and ptrdiff_t, respectively. > int main() > { > std::vector < int, smart_allocator<int> > cInt; > } Aha: int & != smart_allocator<int>::reference == smart<int> & Maybe, std::vector< smart<T>, smart_allocator<T> > would work. [snip] Best Kai-Uwe Bux -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Phil Bouchard on 21 Jun 2008 07:27 "Kai-Uwe Bux" <jkherciueh(a)gmx.net> wrote in message news:g3hk32$hr4$1(a)aioe.org... [...] > Your allocator violates [20.1.5/4] > > Implementations of containers described in this International Standard > are > permitted to assume that their Allocator template parameter meets the > following two additional requirements beyond those in Table 32. > [...] > ? The typedef members pointer, const_pointer, size_type, and > difference_type are required to be T*,T const*, size_t, and ptrdiff_t, > respectively. How unfortunate! It wouldn't make sense having to explicitly define these typedefs inside the allocator in the first place because they can't even be changed. >> int main() >> { >> std::vector < int, smart_allocator<int> > cInt; >> } > > Aha: > > int & != smart_allocator<int>::reference == smart<int> & > > Maybe, > > std::vector< smart<T>, smart_allocator<T> > > > would work. Thanks but I tried it and I was still stuck into __normal_iterator not having the right constructor: ....stl_vector.h: In member function `__gnu_cxx::__normal_iterator<typename _Alloc::const_pointer, std::vector<_Tp, _Alloc> > std::vector<_Tp, _Alloc>::begin() const [with _Tp = smart_ptr<vector>, _Alloc = smart_allocator<vector>]': ....stl_vector.h:221: instantiated from `std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = smart_ptr<vector>, _Alloc = smart_allocator<vector>]' shifted_ptr_test2.cpp:66: instantiated from here ....stl_vector.h:322: error: no matching function for call to `__gnu_cxx::__normal_iterator<const smart<vector>*, std::vector<smart_ptr<vector>, smart_allocator<vector> > >::__normal_iterator(smart_ptr<vector>* const&)' ....stl_iterator.h:587: note: candidates are: __gnu_cxx::__normal_iterator<const smart<vector>*, std::vector<smart_ptr<vector>, smart_allocator<vector> > >::__normal_iterator(const __gnu_cxx::__normal_iterator<const smart<vector>*, std::vector<smart_ptr<vector>, smart_allocator<vector> > >&) ....stl_iterator.h:603: note: __gnu_cxx::__normal_iterator<_Iterator, _Container>::__normal_iterator(const _Iterator&) [with _Iterator = const smart<vector>*, _Container = std::vector<smart_ptr<vector>, smart_allocator<vector> >] ....stl_iterator.h:600: note: __gnu_cxx::__normal_iterator<_Iterator, _Container>::__normal_iterator() [with _Iterator = const smart<vector>*, _Container = std::vector<smart_ptr<vector>, smart_allocator<vector> >] I can always copy & paste my own STL as seen what happens. Regards, -Phil -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Kai-Uwe Bux on 21 Jun 2008 17:58 Phil Bouchard wrote: > > "Kai-Uwe Bux" <jkherciueh(a)gmx.net> wrote in message > news:g3hk32$hr4$1(a)aioe.org... > > [...] > >> Your allocator violates [20.1.5/4] >> >> Implementations of containers described in this International Standard >> are >> permitted to assume that their Allocator template parameter meets the >> following two additional requirements beyond those in Table 32. >> [...] >> ? The typedef members pointer, const_pointer, size_type, and >> difference_type are required to be T*,T const*, size_t, and >> ptrdiff_t, respectively. > > How unfortunate! It wouldn't make sense having to explicitly define these > typedefs inside the allocator in the first place because they can't even > be changed. True. The standard leaves this as a quality of implementation issue. An STL implementation is definitely allowed to support more general allocators. >>> int main() >>> { >>> std::vector < int, smart_allocator<int> > cInt; >>> } >> >> Aha: >> >> int & != smart_allocator<int>::reference == smart<int> & >> >> Maybe, >> >> std::vector< smart<T>, smart_allocator<T> > >> >> would work. > > Thanks but I tried it and I was still stuck into __normal_iterator not > having the right constructor: [snip error messages] Well, gcc uses some nasty tricks. Somewhere in the definition of std::vector<T,A> it does something like this: typedef typename A::template rebind<T>::other true_allocator_type; and then it uses the true_allocator_type for certain things. I suspect that this is the reason, it wouldn't get fooled by using std::vector< smart<T>, smart_allocator<T> > (I am actually not entirely sure whether this behavior is standard compliant; but I think it is ok: containers such as list and map have to rebind the allocator internally anyway.) I guess, you could finally try std::vector< smart<T>, smart_allocator< smart<T> > > where smart_allocator<> would need to be rewritten so that it will strip smart<T> down to T internally. Best Kai-Uwe Bux -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: Unicode Marker: (was cast int to char) Next: implicit conversion |