Bill Heitler
Bill Heitler

Reputation: 199

how to pass valarray or vector as argument in C++20

I want a function that can take either a valarray or vector as an argument. The (trivial sample) code below works fine in C++17 (compiles, runs, and gives the right answer), but fails to compile in C++20 with the error message

'GetSum': no matching overloaded function found

It works if I call the pointer version directly, but it's obviously neater if I can just pass the container.

template<class T>
T GetSum(std::valarray<T>& vIn)
{
    return GetSum(&vIn[0], vIn.size());
}

template<class T>
T GetSum(std::vector<T>& vIn)
{
    return GetSum(&vIn[0], vIn.size());  // could use .data() here
}

// pointer version
template<class T>
T GetSum(T* vIn, size_t n)
{
    T sum{};
    for (size_t i = 0; i < n; ++i)
        sum += vIn[i];
    return sum;
}


void OnTest()
{
    std::vector<double> vec(10, 1);
    std::valarray<int> val(3, 10);

    double x = GetSum(vec);
    int i = GetSum(val);
...

Sorry for my ignorance, but can someone tell me what I am doing wrong? (FYI I asked a question on this topic a while back, which was how I got the C++17 code working OK, but now I'm trying to move to C++20 and find that my code no longer works).

Upvotes: 1

Views: 94

Answers (1)

user12002570
user12002570

Reputation: 1

can someone tell me what I am doing wrong?

The problem is that you're trying to call the pointer version of GetSum before declaring it. In other words, when you wrote GetSum(&vIn[0], vIn.size()) the compiler can't find the suitable version because name lookup only considers declaration at or before that point.

To solve this, you can move its declaration before using/calling it as shown below:

//first declare/define this
template<class T>
T GetSum(T* vIn, size_t n)
{
    T sum{};
    for (size_t i = 0; i < n; ++i)
        sum += vIn[i];
    return sum;
}

//now you can use the above
template<class T>
T GetSum(std::vector<T>& vIn)
{
    //now this'll work because we've already declared the pointer version above
    return GetSum(&vIn[0], vIn.size());  
}

template<class T>
T GetSum(std::valarray<T>& vIn)
{
    return GetSum(&vIn[0], vIn.size());
}

Working demo

Upvotes: 1

Related Questions