2

标准 C++17 实现 vector any, all:

template<class C, class T>
bool contains(const C& c, const T& value) {
  return std::find(c.begin(), c.end(), value) != c.end();
}

template<class C, class... T>
bool any(const C& c, T&&... value) {
  return (... || contains(c, value));
}

template<class C, class... T>
bool all(const C& c, T&&... value) {
  return (... && contains(c, value));
}

用法如

std::array<int, 6> data0 = { 4, 6, 8, 10, 12, 14 };
assert( any(data0, 10, 55, 792));
assert( !any(data0, 11));

assert( all(data0, 6, 14, 8));
assert( !all(data0, 6, 7, 8));

是否有一种类似的方式来定义only,当且仅当向量的唯一值集与输入值匹配时才返回 true?所以以下断言将成立

std::array<int, 6> data1 = { 1, 1, 2, 1, 2 };
assert( only(data1, 1, 2));
assert( !only(data1, 1));
4

3 回答 3

3

您可以提供一个count功能:

template<class C, class T>
auto count(const C& c, const T& value) {
  return std::count(c.begin(), c.end(), value);
}

only这样写:

template<class C, class... T>
bool only(const C& c, T&&... value) {
  return (count(c, value) + ...) == c.size();
}

这会处理 中的重复元素c,但要求values 是唯一的。

这是一个演示

于 2020-06-10T14:19:03.373 回答
2
template<class C, class...Ts>
bool only( C const& c, Ts&&...ts ) {
  std::size_t count = (std::size_t(0) + ... + contains(c, ts));
  return count == c.size();
}

这会计算列表ts...中有多少c,如果您发现 ear 的数量等于 的元素,则返回 true c。现在假设 和 的唯一cts

我们只是将计数移到onlystd 算法中并在其中进行测试:

template<class C, class...Ts>
bool only( C const& c, Ts&&...ts ) {
  using std::begin; using std::end;
  auto count = std::count_if( begin(c), end(c), [&](auto&& elem) {
    return ((elem == ts) || ...);
  } );
  return count == c.size();
}

鲍勃是你的叔叔。

我们也可以做一个notcontains基于only算法,​​但我认为这更复杂。

于 2020-06-10T14:16:18.560 回答
0

它不使用折叠表达式,但它应该可以工作

template<class C, class... T>
bool only(const C& c, T&& ...vals) {
    auto ilist = {vals...}; //create initializer_list

    for (auto el : c) {
        if (!contains(ilist, el)) return false;
    }
    return true;
}

使用折叠表达式而不是std::initializer_list

template<class T, class... Ts>
bool is_one_of(const T& val, Ts&& ...vals)
{
    return ((val == vals) || ...);
}

template<class C, class... Ts>
bool only(const C& c, Ts&& ...vals)
{
    for (const auto& el : c) {
        if (!is_one_of(el, vals...)) return false;
    }
    return true;
}

// or if you hate raw loops
template<class C, class... Ts>
bool only(const C& c, Ts&& ...vals)
{
    using std::beign; using std::end;
    auto it = std::find_if(begin(c), end(c), [&](const auto& el) {
        return !is_one_of(el, vals...);
    });
    return (it == end(c));
}
于 2020-06-10T14:11:51.757 回答