2

Is it possible to customize the reference of a std::vector. Until C++11 it seemed to be possible through the Allocator template parameter. But not anymore?

According to the documentation, http://en.cppreference.com/w/cpp/container/vector, reference is now always value_type and value_type is always the template parameter T.

It seems to be impossible even using allocator_traits, http://en.cppreference.com/w/cpp/memory/allocator_traits

Is there a workaround for this?

If not, does it means that I have to specialize the entire std::vector and probably reproduce all its functionality if I want to have a special reference type based on the allocator?

If this is so, generally speaking what is the logic for all these constrains? To force the user to use std::vector<T, A> to always manage regular memory (in which, value_type = T, reference = T& and pointer = T*?)


Note: I am aware of the std::vector<bool> controversy. However this a bit more general because in principle I need a custom std::vector<RegularType, special_allocator<RegularType>> mainly to control the return type of operator[](int) to a special proxy object.


Specific implementation: I am looking at GCC 6.3.1's stdlib source and in std_vector.h one can read:

template<typename _Tp, ...>
class vector : ...{
   ...
   public:
   typedef typename _Alloc_traits::reference          reference;
};

which seems to indicate that it is still possible to specify a reference type via the allocator (_traits?).

According to the documentation, allocator or the allocator_traits doesn't need to have a reference type. Plus, I don't know how to customize this type anyway.

Is GCC not following the standard? Or is it simply that indirectly allocator_traits<Allocator>::reference is forced to be allocator_traits<Allocator>::value_type&?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
alfC
  • 14,261
  • 4
  • 67
  • 118

1 Answers1

3

If this is so, generally speaking what is the logic for all these constrains?

The purpose is to stop promising things C++ cannot deliver.

Back in the C++98/03 days, it was thought that proxy types, specialized references and the like could really work with standard library containers and algorithms. By the time C++11 rolled around, it had become abundantly clear that... no, they really can't. Or at least, not with the same semantics as an actual language reference.

With that wisdom in mind, C++11 removed a lot of these no-longer-reasonable customization points. The typedefs were left in, but mainly for backwards-compatibility's sake.

which seems to indicate that it is still possible to specify a reference type via the allocator (_traits?).

No, it isn't. This is a bug in libstdc++; reference is required to be value_type& for containers now. allocator_traits has no reference customization point.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thank you for the very straight forward response. Maybe once we have smart references (overload dot) they can put back these customization points. Do you have a recommendation for a workaround? or at least a mindset?, after all, if one now wants something that has the internal logic of a `std::vector`, it seems that one has to roll out a complete reimplementation of the class. – alfC Jan 11 '17 at 01:33
  • On the "bug" in gcc: Actually, it looks like gcc has a "parallel" `allocator_traits` called `__gnu_cxx::__allocator_traits` that is disconnected from `std::allocator_traits`, and it is used in `std::vector`. So `std::allocator_traits::< >::reference`, it is still not a customization points. (I think the standard went overboard with removing customization points, I customized `__gnu_cxx::__alloc_traits` for fun and it seems to work.) – alfC Jan 11 '17 at 01:37
  • Perhaps an option is to customize `boost::container::vector` instead. It seems to still have many customization points that `std::vector`/`std::allocator_traits` lost. – alfC Jan 11 '17 at 01:46
  • http://www.boost.org/doc/libs/1_59_0/doc/html/interprocess/allocators_containers.html#interprocess.allocators_containers.containers_explained.stl_container_requirements – alfC Jan 11 '17 at 21:06
  • I looked into this problem again, `std::vector` now (C++11) is so constrained that a `std::vector::iterator` might as well be a `T*` and be done with it. – alfC Mar 22 '17 at 16:29
  • I gave a shot to Boost Container vector, and failed miserably because of a very small detail, `resize`. https://stackoverflow.com/questions/44958308/can-boost-container-vector-manage-memory-through-non-raw-pointers – alfC Jul 06 '17 at 20:41