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).
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());
}