将函数指针存储到 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 );
您有两个主要选择:
用 lambda 包起来:
auto f = [](float a, float b) { return std::max(a, b); };
// Note there's no by-reference behaviour in this lambda.
如果你想要更可重用的东西,你需要单独包装它,例如,作为不需要恶作剧传递的东西:
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.
的一些特殊情况外,这是不允许的。
我试图将函数 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 );
您有两个主要选择:
用 lambda 包起来:
auto f = [](float a, float b) { return std::max(a, b); }; // Note there's no by-reference behaviour in this lambda.
如果你想要更可重用的东西,你需要单独包装它,例如,作为不需要恶作剧传递的东西:
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.
的一些特殊情况外,这是不允许的。