11

I've read here and other places that when iterating a std::vector using indexes you should:

std::vector <int> x(20,1);
for (std::vector<int>::size_type i = 0; i < x.size(); i++){
  x[i]+=3;
}

But what if you are iterating two vectors of different types:

std::vector <int> x(20,1);
std::vector <double> y(20,1.0);
for (std::vector<int>::size_type i = 0; i < x.size(); i++){
  x[i]+=3;
  y[i]+=3.0;
}

Is it safe to assume that

std::vector<int>::size_type

is of the same type as

std::vector<double>::size_type

?

Would it be safe just to use std::size_t?

alfC
  • 14,261
  • 4
  • 67
  • 118
Mark
  • 106,305
  • 20
  • 172
  • 230
  • If you have been taught about iterating like this, you've been taught wrong. Apart from the `i++` that any decent compiler should optimize to a `++i`, you still call `x.size()` at each turn of the loop, which if it is non-trivial and not inline is wasteful. – Matthieu M. Feb 04 '10 at 17:49
  • @Matthieu, just a quick and dirty example to illustrate my question. I should also be using iterators and not doing it by index. – Mark Feb 04 '10 at 19:09
  • If you are paranoid you can use `std::common_type<...::size_type, ...::size_type>` , https://en.cppreference.com/w/cpp/types/common_type – alfC Feb 12 '22 at 00:01

5 Answers5

8

Yes, for almost any practical purpose, you can just use std::size_t. Though there was (sort of) an intent that different containers could use different types for their sizes, it's still basically guaranteed that (at least for standard containers) size_type is the same as size_t.

Alternatively, you could consider using an algorithm, something like:

std::transform(x.begin(), x.end(), x.begin(), std::bind2nd(std::plus<int>(), 3));
std::transform(y.begin(), y.end(), y.begin(), std::bind2nd(std::plus<double>(), 3.0));
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

In general, C++ standard doesn't give such guarantees: neither equality of size_types for differently parametrized containers, nor equality to size_t.

Alexander Poluektov
  • 7,844
  • 1
  • 28
  • 32
  • +1. And you were correct, the `std::size_t` guarantee is for allocators only. I thought `std::vector::size_type` had to be equal to `Allocator::size_type`, but apparently not. – avakar Feb 04 '10 at 15:05
  • @avakar:The situation is that the standard allocator uses size_t for its size_type, and all known implementations of the standard containers pass the size_type through from their associated allocator. As a result, unless you write your own allocator, it's going to be size_t. From a practical perspective, size_t is essentially always going to work, regardless of what they use as size_type -- e.g. `::operator new` uses size_t for the size of allocation, and essentially all other allocation goes through that (at least by default). – Jerry Coffin Feb 04 '10 at 15:13
2

I think you can safely assume that size_type is an unsigned nonegative integer. You can't rely on much beyond that. Sure, most containers have a size_type which is the same as size_t but there are no guarantees.

The SGI documentation and this source http://www.cplusplus.com/reference/stl/vector/ seem to agree on the point.

You may also want to take a look to this solution for your problem: http://rosettacode.org/wiki/Loop_over_multiple_arrays_simultaneously#C.2B.2B

I hope this helps.

batbrat
  • 5,155
  • 3
  • 32
  • 38
1

Well, I think that:

 for (std::vector<int>::size_type i = 0; i < x.size(); i++){

is something of a council of perfection - are you expecting your vectors to be really gigantic? Personally, I use unsigned int, with zero problems.

And now I suppose the downvotes will begin...

  • @Neil, love the "council of perfection". I was using unsigned int but reading stuff like this: http://stackoverflow.com/questions/409348/iteration-over-vector-in-c, makes we worry. Probably un-needed worry. – Mark Feb 04 '10 at 15:08
  • @Neil: you'll never live that long -- nobody want to be blamed perfectionist I guess :-D – Alexander Poluektov Feb 04 '10 at 15:10
  • 2
    @Mark If you are using an unsigned type, you are OK, IMHO. litb's answer to the question you linked is (of course) correct, but you have really got to love typing (in both senses) to use size_type. –  Feb 04 '10 at 15:12
-1

You should use iterators instead

std::vector <int> x(20,1);
std::vector <double> y(20,1.0);
std::vector<double>::iterator j = y.begin();
for (std::vector<int>::iterator i = x.begin(); i != x.end(); ++i){
  *i +=3;
  *j +=3.0;
  ++j;
}

Cause there's no guarantee that u size_type would be the same internal type, anyway, for std::vector you could iterate using unsigned int

erick2red
  • 1,312
  • 1
  • 14
  • 19
  • 1
    Why not incrementing `j` in the for control body ? And you too suffer from not using a `max` or `end` variable to check the end of the iteration... stick with `for_each` really ;) – Matthieu M. Feb 04 '10 at 17:54
  • @MatthieuM, how could you use foreach when you need to iterate across two different vectors? Obviously this example is trite and the loops can be separated, I can't think of a way to do it for x[i] = y[i] + 3 – Jamie Cook Mar 01 '10 at 10:54