Reputation: 357
I've had previously-working code fail on moving from g++-5 to g++-6; a previously-deducible template is no longer deducible. A minimal example:
#include <math.h>
template<typename T,typename T1>
T apply(T (*func)(T1), const T1 &val)
{
return func(val);
}
int main(void)
{
double val1 = 0.5, val2 = apply(ceil,val1);
return 0;
}
g++-6 can't seem to find the correct version of ceil
:
foo.cpp: In function ‘int main()’:
foo.cpp:11:44: error: no matching function for call to ‘apply(<unresolved overloaded function type>, double&)’
double val1 = 0.5, val2 = apply(ceil,val1);
^
foo.cpp:4:3: note: candidate: template<class T, class T1> T apply(T (*)(T), const T1&)
T apply(T (*func)(T), const T1 &val)
^~~~~
foo.cpp:4:3: note: template argument deduction/substitution failed:
foo.cpp:11:44: note: couldn't deduce template parameter ‘T’
double val1 = 0.5, val2 = apply(ceil,val1);
g++-5 has no problems and works as expected. Using the Compiler Explorer with g++ 8 at https://godbolt.org/z/oBSopG, I also see a reversion from clang-3.3 (compiles) to clang-3.4 (doesn't compile).
Given that the code still doesn't work, even in current g++, I assume that the error is on my part. What have I done wrong and how can I fix it?
Upvotes: 6
Views: 124
Reputation: 21808
If you are using (or planning to use) C++17, you should know that there is a more robust library function doing what you are trying to do: std::invoke
With it, your example can be reduced to:
#include <cmath>
#include <functional>
int main(void)
{
double val1 = 0.5, val2 = std::invoke(ceil,val1);
return 0;
}
Interestingly, with both your hand-crafted apply
and the library std::invoke
, the code will fail if you write std::invoke(std::ceil, val1)
. This needs further investigation....
Upvotes: 1
Reputation: 1
What have I done wrong and how can I fix it?
The way to fix that is to #include <cmath>
instead of using #include <math.h>
as mentioned in the reference documentation:
#include <cmath> // <<< official header to use.
#include <iostream>
template<typename T,typename T1>
T apply(T (*func)(T1), const T1 &val)
{
return func(val);
}
int main(void)
{
double val1 = 0.5, val2 = apply(ceil,val1);
std::cout << val1 << ' ' << val2<< std::endl;
}
Upvotes: 4