将函数指针存储到 std::max 的自动变量

Auto variable to store function pointer to std::max

我试图将函数 std::max 作为模板参数传递给模板化函数,但出于某些原因,编译器打印出无法推断函数类型的错误。一个简单的例子重现了同样的问题。它适用于自己的 max2 函数,但不适用于 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;
}

here 所示,std::max<float> 不是一个单一的、明确的函数。此时,它是一个重载集,还有两种可能:

constexpr const float& max( const float& a, const float& b );
constexpr float max( std::initializer_list<float> ilist );

您有两个主要选择:

  1. 用 lambda 包起来:

     auto f = [](float a, float b) { return std::max(a, b); };
     // Note there's no by-reference behaviour in this lambda.
    
  2. 如果你想要更可重用的东西,你需要单独包装它,例如,作为不需要恶作剧传递的东西:

     struct max_fn {
         template<typename T>
         const T& operator()(const T& a, const T& b) const {
             return std::max(a, b);
         }
     };
    

显然 #2 带有重要的样板文件,并且忽略了其他重载和 constexpr。未来,希望你们能做得更好。今天,您可以使用宏来模拟这样的事情(最简单的方法是将宏展开为 lambda)。我遇到过至少一个 LIFT 执行此操作的宏。

第三个选项可能很有吸引力,因为它是一行(丑陋的一行,但只有一行),并且正在转换为正确的函数指针类型。但是,除了根据 [namespace.std]/6.

的一些特殊情况外,这是不允许的。