There is no clearly defined way to achieve this functionality. With huge caveats and warnings, it can (for at least one version of GCC) hack, as shown below, or you could write something with clearer behavior, but based on the current implementation of the std::vector compiler ....
So ... hacked. This will not work if insert / erase / resize / reserve / clear / push_back or any other operation affecting the common vector. This may not be portable / continue to work / work with all levels of optimization / work on Tuesdays / use at your own risk, etc. It depends on optimizing an empty base class.
You need a special allocator, but there is a catch: the allocator cannot have any state or it will change the binary layout of the vector object, so we will end with this:
#include <iostream> #include <vector> template <typename Container> // easy to get this working... void f(Container& v) { std::cout << "f() v.data() " << v.data() << ", v.size() " << v.size() << '\n'; for (int& n : v) n += 10; } void g(std::vector<int>& v) // hard to get this working... { std::cout << "g() v.data() " << v.data() << ", v.size() " << v.size() << '\n'; for (int& n : v) n += 100; } int* p_; // ouch: can't be a member without changing vector<> memory layout struct My_alloc : std::allocator<int> { // all no-ops except allocate() which returns the constructor argument... My_alloc(int* p) { p_ = p; } template <class U, class... Args> void construct(U* p, Args&&... args) { std::cout << "My_alloc::construct(U* " << p << ")\n"; } template <class U> void destroy(U* p) { std::cout << "My_alloc::destroy(U* " << p << ")\n"; } pointer allocate(size_type n, std::allocator<void>::const_pointer hint = 0) { std::cout << "My_alloc::allocate() return " << p_ << "\n"; return p_; } void deallocate(pointer p, size_type n) { std::cout << "deallocate\n"; } template <typename U> struct rebind { typedef My_alloc other; }; }; int main() { std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::cout << "main() v.data() " << v.data() << '\n'; My_alloc my_alloc(&v[3]); // first element to "take over" std::vector<int, My_alloc> w(3, my_alloc); // num elements to "take over" f(w); g(reinterpret_cast<std::vector<int>&>(w)); for (int n : v) std::cout << n << ' '; std::cout << '\n'; std::cout << "sizeof v " << sizeof v << ", sizeof w " << sizeof w << '\n'; }
Output:
main() v.data() 0x9d76008 My_alloc::allocate() return 0x9d76014 My_alloc::construct(U* 0x9d76014) My_alloc::construct(U* 0x9d76018) My_alloc::construct(U* 0x9d7601c) f() v.data() 0x9d76014, v.size() 3 g() v.data() 0x9d76014, v.size() 3 0 1 2 113 114 115 6 7 8 9 sizeof v 12, sizeof w 12 My_alloc::destroy(U* 0x9d76014) My_alloc::destroy(U* 0x9d76018) My_alloc::destroy(U* 0x9d7601c) deallocate
See how it works here
Tony delroy
source share