Search code examples
c++arraysfor-loopstdarray

How to use either array<int,10> or array<int,4> at runtime?


I want my code to use either a short version of an array, or a long version (with more elements in it) depending on a runtime value.

constexpr std::array<int, 10> longArray{0,1,2,3,4,5,6,7,8,9};
constexpr std::array<int,4> shortArray{0,3,6,9};
auto const& myArray = useShortArray ? shortArray : longArray;
for( auto n : myArray ) {
     // Do the stuff
}

As above, there's an error because the arguments to the ternary operator are not the same.

How can I do this?

The only way is to declare two begin and end iterators that are assigned. But this leads to use the old for on iterators and requires to dereference the iterator at every use within the for block.

auto const& myBegin = useShortArray ? shortArray.begin() : longArray.begin();
auto const& myEnd   = useShortArray ? shortArray.end()   : longArray.end();
for( auto it = myBegin ; it != myEnd ; ++it ) {
    // use *it
}

Is there some way to write it (maybe copying the arrays to vectors?) to avoid reverting to the begin/end version?


Solution

  • You can use a lambda for example:

    auto doTheStuff = [](auto& myArray) {
        for(auto n : myArray) {
             // Do the stuff
        }
    };
    
    useShortArray ? doTheStuff(shortArray) : doTheStuff(longArray);
    

    Alternatively, if you want to give it a name this can be a template function.

    Another approach is to use a span, such as the upcoming std::span in C++20. In this approach the template function that accepts different sized arrays is the constructor of the span. This way the function that uses the range doesn't need to be a template.