c++std-span

What's the best way to pass a r-value/temporary collection to a function taking a std::span?


I've been trying to start using std::span<const T> in places where I would have previously used const std::vector<T>&. The only sticking point I have is illustrated in the following:

#include <iostream>
#include <vector>
#include <span>
#include <numeric>

double mean1(std::span<const double> vals) {
    return std::accumulate(vals.begin(), vals.end(), 0.0) / vals.size();
}

double mean2(const std::vector<double>& vals) {
    return std::accumulate(vals.begin(), vals.end(), 0.0) / vals.size();
}


int main() {
    std::vector<double> foo = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
    auto v = mean1(foo);
    std::cout << v << "\n";

    v = mean2( { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 } );
    std::cout << v << "\n";

    v = mean1({ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 } ); // << this is an error
    std::cout << v << "\n";

}

I know that passing std:vector{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 } would work but that is pretty verbose. initializer_list is even more verbose. Just wondering if I am missing something obvious here.

The specific error from Visual Studio is

C2664 'double mean1(std::span<const double,18446744073709551615>)': cannot convert argument 1 from 'initializer list' to 'std::span<const double,18446744073709551615>'

I think, basically, std::span doesn't have a constructor that takes an initializer list.


Solution

  • you can use

    mean1( {{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }} );
    

    which invoke the raw array constructor.


    if you want to specify the type, I'd suggest

    mean1( std::initializer_list{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 } )
    

    which prevent the potential construction of another container. (which still construct a initializer_list anyway)