Is there a generic way to get `size_type` from a C++ container?

223 views Asked by At

Is it possible to get a type alias for size_type from a container such as std::vector or std::map without supplying a value_type of some kind?

I am writing a program where I need the size_type from two different map types. If, however, I create a typedef for the first map type, the name size_type is not available for the second. My workaround (a.k.a., "kludge") solution, it to tell a lie.

std::map<char, int> letters;
std::map<std::string, int> digraphs, trigraphs;

// This lie is good enough for both map types.
using size_type = typename std::map<int, int>::size_type;

In other cases, I would just prefer not to supply a value_type. Here is a contrived example.

// Yes, I know this can be cleaned up by doing it in stages, but ugh!
using size_type = typename std::map<std::string, std::pair<std::string, std::string>>::size_type;

At the end of the day, we all know size_type is probably going to be an alias for std::size_t, even in corner cases such as std::vector<bool>. Nevertheless, I still try to do things the "correct" way, by using size_type.

So, is there a way to get size_type without supplying value_type?

2

There are 2 answers

0
user17732522 On BEST ANSWER

So, is there a way to get size_type without supplying value_type?

No, because size_type can be a different type for every value_type.

Of course, as you said yourself, that's normally not the case and size_type is almost always just std::size_t, but both the standard library implementation itself, as well as user-defined specializations of the container templates, are allowed to define size_type differently for different value_type and there is no requirement that it must be related to std::size_t.

There isn't even any requirement that size_type must be smaller or larger than std::size_t. If you want to have generic library code that works with any standard-conforming implementation, you'll have to always consider size_type individually and make no assumptions about their relation.

1
tbxfreeware On

Thanks for all the help.

I have upvoted the answer given by @user17732522, and marked it as the accepted answer.

In addition, however, @Nelfeal gave the best answer for the specific use case in the original question. Instead of creating my own typedef for size_type, I should use std::size_t, and—if I am worried that a container might be using something else—add static asserts in the place where the using statement was before.

std::map<char, int> letters;
std::map<std::string, int> digraphs, trigraphs;

static_assert(std::is_same_v<std::size_t, std::map<char, int>::size_type>);
static_assert(std::is_same_v<std::size_t, std::map<std::string, int>::size_type>);

// From here forward, std::size_t is guaranteed to be the correct size.
// I can use it directly, or optionally, create a type alias that is not a lie.
using size_type = std::size_t;