Search code examples
c++loopsauto

Get to STL container's size_type using a variable


I want to write index-based for loops in a simple way. Since my code has to run in 32 and 64 bit, I get lots of warnings about implicit conversions because I usually use 32 bit integers but the STL uses 64 bit integers in 64 bit.

std::vector<MyClass> c;
for (FOO ui = 0, uiEnd = c.size(); ui < uiEnd; ++ui){...}
  • FOO = unsigned int works on 32 bit but generates warnings on 64 bit.
  • FOO = size_t works on 32 and 64 bit but is not entirely correct because the Standard does not require std::vector<MyClass>::size_type == size_t.
  • FOO = auto does not work (which is quite unfortunate) because it sets the type for each variable individually, so the type of the literal 0 (or 0UL or whatever) which differs from c.size() (in 32 or 64 bit, the type of c.size() can differ, so I cannot write the correct literal).
  • for (auto uiEnd = c.size(), ui = 0*uiEnd; ui < uiEnd; ++ui){...} works by expressing 0 with the correct type but is obscure.
  • FOO = decltype(c.size()) works but I find it obscure.
  • FOO = std::vector<MyClass>::size_type works but I find it tedious to repeat the type of the container.

I would prefer something like FOO = c::size_type, which clearly expresses what is happening. But is it possible to get the size_type of std::vector<MyClass> using only the variable c? I tried the following things without success:

  • c::size_type
  • typeid(c)::size_type
  • decltype(c)::size_type

Solution

  • Whereas you might use:

    std::vector<MyClass> c;
    
    for (decltype(c)::size_type ui = 0, uiEnd = c.size(); ui < uiEnd; ++ui){...}
    

    I would use:

    std::vector<MyClass> c;
    
    std::size_t index = 0; // as you want index too
    for (auto& myclass : c){...; ++index;}
    

    And even in C++20:

    std::vector<MyClass> c;
    
    for (std::size_t index = 0; auto& myclass : c){...; ++index;}
    

    ranges-v3 has enumerate view:

    std::vector<MyClass> v;
    
    for (const auto& [index, myclass] : v | ranges::v3::views::enumerate) {
        // ...
    }
    

    Demo