0

我想创建一个仿函数,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<>()实现的,所以它跳过了模板和函数参数?

4

2 回答 2

1

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;

您可以通过以下方式明确选择要添加的类型:

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);

完整示例

于 2020-12-03T20:58:56.327 回答
1

您的代码中存在许多问题。

  1. 无法将钳位值传递给运算符(如果使用std::transform),您需要将它们作为构造函数参数传递给plus_clamp. 这意味着它plus_clamp需要是一个模板而不是操作符。
  2. 假设nlstd::numeric_limits是一个模板,所以需要将模板类型传递给它:std::numeric_limits<T>::min()
  3. std::plus<>()只是构造类型而不调用它的运算符。它应该是std::plus<>{}(lhs, rhs)
  4. 当调用std::transform你 passplus_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,则可以使用类模板参数推导,只需使用plus_clamp(10, 100).

于 2020-12-03T21:01:40.143 回答