Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto variable to store function pointer to std::max

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;
}
like image 661
eXXXXXXXXXXX2 Avatar asked Dec 04 '17 01:12

eXXXXXXXXXXX2


1 Answers

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:

  1. 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.
    
  2. 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.

like image 165
chris Avatar answered Oct 18 '22 19:10

chris