0

The following is the code:

#include <vector>
#include <string>

std::vector<std::string> zip(
    const std::vector<std::string> & a, 
    const std::vector<std::string> & b) {
  std::vector<std::string> result;
  for (int i = 0; ; ++i) {
    bool a_indexable = i < static_cast<int>(a.size()); //I couldn't get what the following two lines mean as I asked in the title, I couldn't get what bool means here and I couldn't get what i < static_cast<int>(a.size()) means here
    bool b_indexable = i < static_cast<int>(b.size());
    if (!a_indexable && !b_indexable) {
      break;
    }
    std::string element;
    if (a_indexable) {
      element += a[i];
    }
    if (b_indexable) {
      element += b[i];
    }
    result.push_back(element);
  }
  return result;
}

I know what static_cast<int> means in the code but I feel confused about its combination especially like i < static_cast<int>(b.size()). Please explain it if you could help me.

JaMiT
  • 14,422
  • 4
  • 15
  • 31
Xinyan Yang
  • 17
  • 1
  • 3

3 Answers3

4

a_indexable is a boolean that indicates if i is a valid index for the vector a.

A naive way of computing a_indexable would be:

bool a_indexable = i < a.size();

However a.size() is of type std::size_t which is an unsigned integer. Mixing signed with unsigned integers is troublesome so most compilers will emit a warning for i < a.size(). The solution is to explicitly cast a.size() to the type of i like in your example:

bool a_indexable = i < static_cast<int>(a.size());
bolov
  • 72,283
  • 15
  • 145
  • 224
  • Not sure what the cast does if `.size()` is greater than `std::numeric_limits::max()`, but it's probably not good. Most practical programs won't have that problem. – Mark Ransom Aug 29 '20 at 23:31
  • 1
    It would probably be better to just make `i` a `size_t` variable. – paxdiablo Aug 29 '20 at 23:35
1

a.size() and b.size() here refers to std::vector::size(). std::vector::size() returns a size_t (usually an unsigned int), not an int.

As you can see in this question, comparing an int to an size_t will give a warning. By static_casting to an int, whoever wrote this code is getting rid of a warning from the compiler.

1

It's actually a way of deciding whether a given index is valid for the vector and therefore ensuring you don't try to read beyond the end of a vector. If the index is less than the size, then it's valid. The cast avoids warnings form mixing signed and unsigned values in the comparison.

However, I probably would have just made i a size_t type so that such casting was unnecessary, especially since i is very limited in scope.


In fact, I would have written it differently so as to avoid that sort of logic altogether, by getting the common length up front (the minimum of both lengths) and then processing it in sections, something like (with some type aliasing goodness to make the code a little mode readable, and as a complete program showing a minimal test harness):

#include <vector>
#include <string>

using vecString = std::vector<std::string>;
vecString zip(const vecString &a, const vecString &b) {
    vecString result;

    auto asz = a.size();
    auto bsz = b.size();
    auto common_sz = std::min(asz, bsz);

    // Handle common size, both vectors are guaranteed
    // to have elements at these indices.

    for (size_t i = 0; i < common_sz; ++i)
        result.push_back(a[i] + b[i]);

    // Handle where sizes differ, only ONE of these loop
    // bodies will be executed, depending on which is
    // larger. Of course, if sizes were identical,
    // neither loop body will execute.

    for (size_t i = common_sz; i < asz; ++i)
        result.push_back(a[i]);

    for (size_t i = common_sz; i < bsz; ++i)
        result.push_back(b[i]);

    return result;
}

#include <iostream>

int main() {
    std::vector<std::string> vec1, vec2;

    vec1.push_back("pax");
    vec1.push_back("is");
    vec1.push_back("clever");

    vec2.push_back("diablo");

    auto zipVec = zip(vec1, vec2);
    for (const auto &zipString: zipVec)
        std::cout << zipString << '\n';
}
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953