118

What is a good clean way to convert a std::vector<int> intVec to std::vector<double> doubleVec. Or, more generally, to convert two vectors of convertible types?

Alan Turing
  • 12,223
  • 16
  • 74
  • 116

2 Answers2

203

Use std::vector's range constructor:

std::vector<int> intVec;
std::vector<double> doubleVec(intVec.begin(), intVec.end());
Harry
  • 3
  • 2
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 1
    So, you could also use the `std::copy(...)` function then? Could you add that to the answer? – Alan Turing Jun 18 '11 at 22:16
  • 3
    @Lex: `copy(v_int.begin(), v_int.end(), back_inserter(v_float));`, or `v_float.resize(v_int.size()); copy(v_int.begin(), v_int.end(), v_float.begin());` – Jon Purdy Jun 18 '11 at 22:31
  • 1
    bad idea, because the constructor version will presize the vector by using the iterator category to note that those are random access iterators and then reserving enough space. Resizing prior to copy is a wasteful zero initialization. – Michael Goldshteyn Jun 18 '11 at 22:57
  • 2
    @MichaelGoldshteyn I don't understand - if you don't specify the size beforehand, then it will be resized automatically whenever the capacity is exceeded (which copies all the elements over and over again). Okay, this is amortized linear time, but I bet that's still a lot slower than a single 0-initialization. Am I missing something about your argument? – Algoman May 11 '18 at 09:42
  • @Algoman: I agree. But yet better is `reserve`. Then you do one allocation and don't uselessly initialize the data to 0. The constructor version in the answer also allocates only once, since it knows how many elements will be inserted. – Cris Luengo Jul 11 '18 at 14:41
  • I think I misunderstood the answer. However I'm wondering if the c'tor version can really deduce how many elements there are directly. I mean if it only has 2 iterators and doesn't know that they are vector-iterators (does it?), I think it must iterate from begin to end to count the elements first. I think this might still be a little faster than 0-initialization, but I'm not 100% sure. If we account for the time it takes to read, compare and write the iterators and the counting-variable, it might be slower. 0-init has 1 indirection more, but c'tor would then have 1 load and 1 inc more. – Algoman Jul 13 '18 at 08:12
  • 2
    @Algoman see `std::distance()` "If it is a random-access iterator, the function uses operator- to calculate this. Otherwise, the function uses the increase operator (operator++) repeatedly." So in this case the amount of elements could be found by subtracting the iterators. Whether the standard library is implemented to use std::distance for an initial reserve() is another question, but https://godbolt.org/z/6mcUFh at least contains a call to std::distance(). – user1556435 May 03 '19 at 12:33
9

Use std::transform algorithm:

std::transform(intVec.begin(), intVec.end(), doubleVec.begin(), [](int x) { return (double)x;});
Yas
  • 4,957
  • 2
  • 41
  • 24
  • 1
    good solution but I believe it is safer to use static_cast() over (double) as it would check if casting is possible in compile time – Or Hirshfeld Mar 09 '23 at 10:48