首页 > 解决方案 > 如何编写一个以比较运算符为参数的函数模板?

问题描述

我的任务是编写一个函数模板,该模板将一个区间作为前 2 个参数,将一个比较运算符作为第三个参数,并使用此比较运算符决定它是否是单调的。

用法示例:

1.

int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

monotonic(a, a+10, std::greater<int>())
const char *a[] = { "apple", "cherry", "plum", "pickle" };
std::vector<std::string> s(a, a+4);
std::ostream_iterator<std::string> os(cout, ", ");
std::copy(s.begin(), s.end(), os);

monotonic(s.begin(), s.end(), std::greater<std::string>())

我一直在谷歌搜索,发现模板应该看起来像这样:

template<class Iter, typename Comparator>
bool monotonic(Iter first, Iter last, Comparator comp){

}

但是,我无法弄清楚我应该如何使用它comp来实际比较数字、字符等。

标签: c++

解决方案


设计 API 和编写代码的最佳方式是使用测试。

template<typename T, typename F = std::less<typename std::iterator_traits<T>::value_type>>
bool isMonotonic(T b, T e, F cmp = {})
{
    if (b == e) return true;
    auto last = b++;
    while (b != e) {
        if (!cmp(*last, *b)) return false;
        last = b++;
    }
    return true;
}

TEST_CASE("isMonotonic") {
    constexpr int growingTale[] = { 1, 2, 7, 10, 22};
    constexpr int notDecrasingTale[] = { 2, 2, 2, 10, 22};

    SECTION("Empty range is alawyas monotonic") {
        auto sameBeginEnd = std::begin(growingTale);
        CHECK(isMonotonic(sameBeginEnd, sameBeginEnd));
        CHECK(isMonotonic(sameBeginEnd, sameBeginEnd, std::greater{}));
    }
    SECTION("One element range is always monotonic") {
        auto b = std::begin(growingTale);
        CHECK(isMonotonic(b, b + 1));
        CHECK(isMonotonic(b, b + 1, std::greater{}));
    }
    SECTION("growing table is monotonic for less operator, but is not for greater operator") {
        auto b = std::begin(growingTale);
        auto e = std::end(growingTale);
        CHECK(isMonotonic(b, e));
        CHECK(!isMonotonic(b, e, std::greater{}));
    }
    SECTION("Not decrasing range is not monotonic, unless <= operator is used") {
        auto b = std::begin(notDecrasingTale);
        auto e = std::end(notDecrasingTale);
        CHECK(!isMonotonic(b, e));
        CHECK(!isMonotonic(b, e, std::greater{}));
        CHECK(isMonotonic(b, e, std::less_equal{}));
    }
}

https://godbolt.org/z/5zbETxTqx


推荐阅读