c++c++20range-based-loop

Usage of std::span with non-iterable type


I was trying out some C++20 when I stumbled upon a rather strange (at least to me) situation. I was expecting the following code to not work with one of my examples (I've specified the expected behavior with comments), but it did work, and I want to know why. Here's the code snippet:

#include <iostream>
#include <span>

using namespace std;

struct simpleType
{
    simpleType(const int id) : id(id) {}

    int id;
};

template <typename IterableType>
void print(const IterableType& sequenceToPrint)
{
    cout << "[ ";

    for(const auto& element : sequenceToPrint)
    {
        cout << element.id << " ";
    }

    cout << "]" << endl;
}

void test()
{
    simpleType arr [] {1,2,3,4,5};
    span arrSpan {arr};

    // This should work
    print(arrSpan); // prints [ 1 2 3 4 5]
    // This should not
    print(arr); // prints [ 1 2 3 4 5 ] as well
}

int main()
{
    test();
}

I wasn't expecting it to work in both situations because, from my understanding, my templated print function should only work with iterable types because of the range based for loop. What am I missing?


Solution

  • For this

    print(arrSpan)
    

    the implicit instantiation of template would be:

    void print<std::span<simpleType, 5> >(const std::span<simpleType, 5>& sequenceToPrint)
    

    and for this

    print(arr)
    

    the implicit instantiation of template would be:

    void print<simpleType[5]>(const simpleType (&sequenceToPrint)[5])
    

    Both are iterable.