Advertisements
I’m trying to create a shorter name for an existing function.
When I use variable templates type deduction fails
#include <iostream>
#include <cmath>
template<class T>
constexpr T (*max)(T, T) = std::fmax<T>;
int main(){
double x = 6.28;
double y = 4.45;
std::cout << (max<int>(x, y)) << std::endl;
}
This is the message from the compiler:
<stdin>:6:28: error: address of overloaded function 'fmax' does not match required type 'int (int, int)'
constexpr T (*max)(T, T) = std::fmax<T>;
^~~~~~~~~~~~
<stdin>:14:16: note: in instantiation of variable template specialization 'max<int>' requested here
std::cout << (max<int>(x, y)) << std::endl;
^
/data/user/0/ru.iiec.cxxdroid/files/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../include/c++/4.9.x/math.h:1200:1: note: candidate template ignored: failed template argument deduction
fmax(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
^
Without using the alias, the call does work
std::cout<< std:fmax<int>(x, y) << std::endl;
>Solution :
Taking addresses of standard library functions is (with few exceptions) not guaranteed to work at all. The standard library is allowed to use different overload sets of templates to implement the specified behavior of calls to std::fmax
. And even the standard specifies fmax
not as a single template with one template parameter, but as multiple overloads, one of which would naively have two template parameters and the rest none.
Instead just define a function calling the other one:
template<class T>
constexpr auto max(T a, T b) {
return std::fmax(a, b);
}
Also:
constexpr
is wrong before C++23, sincestd::fmax
isconstexpr
only since C++23- I’d advice against using
max
as name. There are functions with the namemax
in the standard library. These do behave differently (returning a reference to one of the arguments instead of a copy by-value and having different floating point behavior). This can easily be confusing. - There are overloads of
std::fmax
that allow two differently typed arguments, so your function should probably also accept different types for the parameters. - The behavior is not exactly correct if you specify the return type as
T
. There is a specified overload offmax
which may return a different type. - It is probably not a good idea to alias this at all. I don’t really see a good reason for doing so.