创建你自己的函子,C++
Create your own functor,C++
我想创建一个类似 std::plus<>()
的仿函数,但还要向其添加 std::clamp
功能。
假设它是一个函数 plus_clamp<>(T MIN = numeric_limits<T>::min(), T MAX = ...max())
我开始查看 std::plus<>()
有什么实现,并尝试重复它。
所以我写了这样的东西。
struct plus_clamp {
template<typename T = void>
constexpr T operator()(const T& lhs, const T& rhs, T MIN = nl::min(),T MAX = nl::max()) {
T result = std::plus<>();
result = std::clamp(result, MIN,MAX);
return result;
}
};
但是当我尝试将该函数与 std::transform(a.begin(),a.end(),b.begin(),result.begin(), plus_clamp<>())
一起使用时
我收到编译器错误
error: expected '(' for function-style cast or type construction
error: expected expression(at template parameter arg)
error: expected expression(at function arguments)
我知道我做错了,因为我需要显式传递模板参数和函数参数,但这又提出了一个问题 std::plus<>()
是如何实现的,所以它跳过了模板和函数参数?
您的 plus_clamp
不是模板。因此,您需要删除 <>
:
std::transform(a.begin(),a.end(),b.begin(),result.begin(), plus_clamp())
// ^
另一方面,std::plus<T>
是一个模板。它有一个 operator()
:
constexpr T operator()( const T& lhs, const T& rhs ) const;
您可以明确地 select 要添加的类型:
T result = std::plus<T>()(lhs,rhs);
//^ T == int in your example
//^ create instance
//^ call its operator()
或者您使用默认值 std::plus<>
,即 std::plus<void>
。它有一个 operator()
从它的参数推导出类型:
T result = std::plus<>()(lhs,rhs);
您的代码中存在许多问题。
- 无法将钳位值传递给运算符(如果使用
std::transform
),您需要将它们作为构造函数参数传递给 plus_clamp
。这意味着 plus_clamp
需要是模板而不是运算符。
- 假设
nl
是 std::numeric_limits
它是一个模板,因此需要传递给它的模板类型:std::numeric_limits<T>::min()
std::plus<>()
只是构造类型而不调用其运算符。应该是std::plus<>{}(lhs, rhs)
- 当调用
std::transform
时,您传递 plus_clamp<>()
,在您的原始代码中 plus_clamp
不是模板,因此您只需要 plus_clamp()
.
一个完整的例子是:
#include <algorithm>
#include <functional>
#include <limits>
template<typename T = void>
struct plus_clamp {
constexpr plus_clamp(T MIN = std::numeric_limits<T>::min(),T MAX = std::numeric_limits<T>::max())
: MIN(MIN), MAX(MAX)
{
}
constexpr T operator()(const T& lhs, const T& rhs) {
T result = std::plus<>{}(lhs, rhs);
result = std::clamp(result, MIN,MAX);
return result;
}
T MIN;
T MAX;
};
int main()
{
std::vector<int> a,b, result;
std::transform(a.begin(),a.end(),b.begin(),result.begin(), plus_clamp<int>(10, 100));
}
如果您使用的是 c++17,则可以使用 class 模板参数推导,只需使用 plus_clamp(10, 100)
.
我想创建一个类似 std::plus<>()
的仿函数,但还要向其添加 std::clamp
功能。
假设它是一个函数 plus_clamp<>(T MIN = numeric_limits<T>::min(), T MAX = ...max())
我开始查看 std::plus<>()
有什么实现,并尝试重复它。
所以我写了这样的东西。
struct plus_clamp {
template<typename T = void>
constexpr T operator()(const T& lhs, const T& rhs, T MIN = nl::min(),T MAX = nl::max()) {
T result = std::plus<>();
result = std::clamp(result, MIN,MAX);
return result;
}
};
但是当我尝试将该函数与 std::transform(a.begin(),a.end(),b.begin(),result.begin(), plus_clamp<>())
我收到编译器错误
error: expected '(' for function-style cast or type construction
error: expected expression(at template parameter arg)
error: expected expression(at function arguments)
我知道我做错了,因为我需要显式传递模板参数和函数参数,但这又提出了一个问题 std::plus<>()
是如何实现的,所以它跳过了模板和函数参数?
您的 plus_clamp
不是模板。因此,您需要删除 <>
:
std::transform(a.begin(),a.end(),b.begin(),result.begin(), plus_clamp())
// ^
另一方面,std::plus<T>
是一个模板。它有一个 operator()
:
constexpr T operator()( const T& lhs, const T& rhs ) const;
您可以明确地 select 要添加的类型:
T result = std::plus<T>()(lhs,rhs);
//^ T == int in your example
//^ create instance
//^ call its operator()
或者您使用默认值 std::plus<>
,即 std::plus<void>
。它有一个 operator()
从它的参数推导出类型:
T result = std::plus<>()(lhs,rhs);
您的代码中存在许多问题。
- 无法将钳位值传递给运算符(如果使用
std::transform
),您需要将它们作为构造函数参数传递给plus_clamp
。这意味着plus_clamp
需要是模板而不是运算符。 - 假设
nl
是std::numeric_limits
它是一个模板,因此需要传递给它的模板类型:std::numeric_limits<T>::min()
std::plus<>()
只是构造类型而不调用其运算符。应该是std::plus<>{}(lhs, rhs)
- 当调用
std::transform
时,您传递plus_clamp<>()
,在您的原始代码中plus_clamp
不是模板,因此您只需要plus_clamp()
.
一个完整的例子是:
#include <algorithm>
#include <functional>
#include <limits>
template<typename T = void>
struct plus_clamp {
constexpr plus_clamp(T MIN = std::numeric_limits<T>::min(),T MAX = std::numeric_limits<T>::max())
: MIN(MIN), MAX(MAX)
{
}
constexpr T operator()(const T& lhs, const T& rhs) {
T result = std::plus<>{}(lhs, rhs);
result = std::clamp(result, MIN,MAX);
return result;
}
T MIN;
T MAX;
};
int main()
{
std::vector<int> a,b, result;
std::transform(a.begin(),a.end(),b.begin(),result.begin(), plus_clamp<int>(10, 100));
}
如果您使用的是 c++17,则可以使用 class 模板参数推导,只需使用 plus_clamp(10, 100)
.