Vector<Int>::Size_Type in C++

vector int ::size_type in C++

size_type is a (static) member type of the type vector<int>. Usually, it is a typedef for std::size_t, which itself is usually a typedef for unsigned int or unsigned long long.

Correct usage of vector int ::size_type

Basically, the above code is 'fine' in the sense that it compiles and does the intended job, as others have said.

When they said the intent was to insert ten ints in the vector, the ints are guaranteed positive because of how the loop is formatted, so the unsigned int will just convert into int.

However, I don't believe this is good practice as you said - the size type has nothing to do with the type of the elements being inserted - the size type is basically always an unsigned int. Just using int or value_type would obviously make the intent of the code clearer.

C++: vector int ::size_type variable - what is the point of declaring in this way?

size_type is guaranteed to be large enough for the largest supported vector size, vector::max_size(). int is not: on many common platforms, int has 32 bits, while max_size() is considerably larger than 231.

If you know the size is (and will always be) a small number like 20, then you can get away with using int or any other integer type instead of size_type. If you were to change the program, for example to read the size from the input, then it would go horribly wrong if that value were larger than INT_MAX; while using size_type, it would continue working for any value up to max_size(), which you can easily test for.

How to handle std::vector ... ::size_type being int

Thanks to L. F. for answering the questions.

The real problem, as AMA pointed out, is the use of const in the type parameter of v_a. This lead to a compiler-error and ultimately to the warning stated in my question.

The solution was to remove the const-qualifier and fix the dependent types.

Handling int and std::vector::size_type in comparsion

Your code looks a bit too perfect for my taste.

Breaking it down:

const int res = std::stoi(cmdarg);
if (res >= 0 && static_cast<std::vector<MyClass*>::size_type>(res) < this->container.size())

The if-statement for checking below zero is nice. Personally I would write this as:

if (res < 0)
{
std::cerr << "Negative number " << res <<" given for ..., a positive was expected" << std::endl;
return -1;
}

This leads us to the cast:

auto unsigned_res = static_cast<std::vector<MyClass*>::size_type>(res);

However, size_type this vector always size_t as it uses the std::allocator. In code review, I would request to change this for readability to:

auto unsigned_res = static_cast<std::size_t>(res);

Finally, you can indeed nicely compare it:

if (unsiged_res < container.size())
// Do something

Note that I mentioned both the comparison and the cast, as this needs to happen in that order. On top of that, you also need some exception handling for when std::stoi fails, see it's documentation

For more details on how to correctly deal with signed/unsigned, I can recommend this article on ithare.

When should I use vector int ::size_type instead of size_t?

The primary time to use size_type is in a template. Although std::vector<T>::size_type is usually size_t, some_other_container<T>::size_type might be some other type instead1. One of the few things a user is allowed to add to the std namespace is a specialization of an existing template for some user defined type. Therefore, std::vector<T>::size_type for some oddball T could actually be some type other than size_t, even though the base template defined in the standard library probably always uses size_t.

Therefore, if you want to use the correct type for a specific container inside a template that works with that container, you want to use container::size_type instead of just assuming size_t.

Note, however, that generic code should rarely work directly with a container. Instead, it should typically work with iterators, so instead of container<T>::size_type, it would typically use something like std::iterator_traits<WhateverIterator>::difference_type instead.


  1. And for some specific T, vector<T>::size_type might be a different type as well--one of the few things you're allowed to put into the std namespace is a specialization of an existing class for a user-defined type, so for some T, vector<T> could use a completely different container than for most other types. This is typical for vector<bool>, but possible for other types as well.

difference between size_type and int

vector<double>::size_type is guaranteed to cover the full range of possible values of the size of a vector<double>. An int is not.

Note that vector<double>::size_type is usually the same as std::size_t, so in general it would be OK to use the latter. However, custom allocators can result in the a vector with a size_type different to std::size_t.

Is `size_t` always an alias for `vector int ::size_type` or any other container type?

std::vector guarantees that pointers are valid iterators for its entire sequence, because vector::data returns "A pointer such that [data(), data() + size()) is a valid range." That's pointer addition, which is defined over std::ptrdiff_t, which is the signed version of std::size_t.

Also, [iterator.requirements.general]/6 applies:

… for integral values n and dereferenceable iterator values a and (a + n), *(a + n) is equivalent to *(addressof(*a) + n)

It's possible for vector::size_type to be narrower than std::size_t, for example 32 bits on a 64-bit system. But it's not something I'd worry about.



Related Topics



Leave a reply



Submit