I'm trying to pass function std::max
as template parameter to a templated function, but for some reasons compiler prints error that function type cannot be deduced. A simple example reproduces the same issue. It works with own max2
function but doesn't work with STL std::max
:
#include <algorithm>
template <class T>
T max2(const T& a, const T& b) { return std::max(a, b); }
int main() {
#if 1
auto f = max2<float>;
#else
// error: unable to deduce ‘auto’ from ‘max<float>’
auto f = std::max<float>;
#endif
float max_val = f(1.0f, 2.0f);
return 0;
}
As seen here, std::max<float>
isn't a single, unambiguous function. At this point, it's an overload set and there are still two possibilities:
constexpr const float& max( const float& a, const float& b );
constexpr float max( std::initializer_list<float> ilist );
You have two main options:
Wrap it in a lambda:
auto f = [](float a, float b) { return std::max(a, b); };
// Note there's no by-reference behaviour in this lambda.
If you want something more reusable, you'll need to wrap it separately, e.g., as something that doesn't require shenanigans to pass around:
struct max_fn {
template<typename T>
const T& operator()(const T& a, const T& b) const {
return std::max(a, b);
}
};
Obviously #2 comes with significant boilerplate, and that's ignoring other overloads and constexpr
. In the future, it is expected that you will be able to do better. Today, you could emulate such a thing with a macro (most simply done by making the macro expand into a lambda). I've come across at least one LIFT
macro that does this.
There's a third option that can be appealing because it's one line (an ugly line, but one line), and that's casting to the correct function pointer type. However, this isn't allowed except in a few special cases per [namespace.std]/6.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With