1

I recently started working with C++ again, after I worked with it in days of yore when the STL wasn't as popular. Well, the STL is great, but I need to wrap an array of mine in a vector for utilizing STL goodness - without copying anything. So, I read this SO question:

Wrapping dynamic array into STL/Boost container?

Surprisingly, most answers, including the accepted one, did not suggest a solution which actually yields a vector... I don't know, maybe coming living in the Java world for a while made me a fan of interfaces. Anyway, one answer by IdanK did suggest getting the vector 'class' (rather, the template) to accommodate this - replacing the allocator with code which uses the backing array.

I'm wondering why this isn't a widely-used solution, why it's not part of STL or Boost, why people don't link to typical implemenation. Are detriments to this approach which I'm failing to notice?

Community
  • 1
  • 1
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 2
    What would be the purpose of "wrapping" a dynamically allocated array with a `std::vector`? – Zac Howland Dec 20 '13 at 18:37
  • 1
    From a pure design standpoint: what you want isn't a vector, but something that looks like a vector. It will be much easier to make your thing look more like a vector than to make a vector look more like your thing. – Casey Dec 20 '13 at 18:45
  • @Casey: I want something which I can pass to functions which take a vector - not a ranged container or a being-end iterator pair etc. The latter would let me avoid the wrapper, but I don't control the world's code... – einpoklum Dec 20 '13 at 18:49
  • @einpoklum This hypothetical function that takes a vector parameter ... who wrote/controls it? And what does it actually look like? – Zac Howland Dec 20 '13 at 18:53
  • @einpoklum And there is the rub. Functions which take a vector are actually pretty rare because of the problem you mention above, there is no good way to "wrap" memory that the vector doesn't allocate itself. This is cuz a vector isn't defined as what you think it is (take a look at vector, for example). – IdeaHat Dec 20 '13 at 18:54
  • @MadScienceDreams: Just for curiosity, and even though I don't control other people's functions - what alternatives are there, assuming you're not talking about taking iterators, but rather - something which, down below, is an in-memory array ? – einpoklum Dec 20 '13 at 20:05
  • @einpoklum In general, if you HAVE to pass an vector from something else, then you have to copy, no exceptions :-/. I like iterators, but they typically require a template definition of the function. In the end, the most flexible, cross platform, and language independent (between C and C++) way is to force everyone to pass around const int*, but this has all its own problems, including memory management, and what if I wanna use lists? No good solution here. – IdeaHat Dec 20 '13 at 20:15
  • @einpoklum If you do have functions have take a `std::vector`: if they're not templates, then they take a `std::vector` with a *default* allocator (so no way to use your dynamic array). Taking a `std::vector` implies that the function *truly needs* a `vector`, not just a contiguous sequence of elements (for example, to resize the vector). Otherwise, don't take `std::vector` but either iterators (for operations that don't modify the container itself but only the elements) or some other type wrapping an underlying sequence. – dyp Dec 20 '13 at 20:35
  • @DyP: That kind of explains things. Bummer. – einpoklum Dec 20 '13 at 23:19

1 Answers1

4

No, there is no standard way of turning

int a[34];

into

std::vector<int>

so you can pass it to a function like

void f(const std::vector<int>& v);

HOWEVER as I see it you have two options, either use a vector at the callsite as that is the type you utilmately need to use and it's adavantagous to a raw array in pretty much every way. Or modify the function to operator on iterators:

template<typename Iter>
void f(Iter first, Iter last);

Then that function can be used with vector, deques, sets, and even raw arrays like so:

std::set<int> s { 1,2,3,4 };
std::vector<int> v { 1,2,3,4 };
int ar[4] { 1,2,3,4 };
f(begin(ar), end(ar));
f(begin(v), end(v));
f(begin(s), end(s));

Personally I would do both though, use a vector at the callsite, and change your func to operate on iterators to decouple it from a particular container.

And to answer your question directly.

I'm wondering why this isn't a widely-used solution, why it's not part of STL or Boost, why people don't link to typical implemenation. Are detriments to this approach which I'm failing to notice?

It's not a widely catered to problem because the idiomatic way to do deal with the issue is to use a generic iterator interface. (Look at the interface to the containers, like std::vector::insert it doesn't take a vector but a pair of iterators).

EDIT:

If you have no other choices, then you're going to have to copy the data:

int arr[4];
//c++11
std::vector<int> v ( begin(arr), end(arr) );
//c++03
std::vector<int> v ( arr, arr+4 );
111111
  • 15,686
  • 6
  • 47
  • 62
  • Well, the thing is, I'm _getting_ an array and I need to _pass_ a vector. This is out of my control. So, both options are off. My question is only about what's the best approach to wrapping an array to be a vector. – einpoklum Dec 20 '13 at 20:04
  • @einpoklum: Can't be done. You can make a vector with a custom allocator that is backed by the array, but the vector will erase your erray before it tries to use it, and I think that would defeat the point. Your only option is to copy the data like this answer shows. – Mooing Duck Dec 20 '13 at 22:21
  • Umm, won't it try to use the allocator to erase the array? The allocator will simply have `destroy()` do nothing. Ok, maybe [not simply](http://i1.kym-cdn.com/photos/images/original/000/038/834/drive_into_mordor.png). – einpoklum Dec 20 '13 at 23:18
  • Changing the allocator changes the type though. a `std::vector` can not be passed to a function expecting `std::vector`. – 111111 Dec 20 '13 at 23:29