初学者如何使用标准::any_of?
How to use std::any_of for a beginner?
我想将一个值与其他几个值进行比较,并检查它是否至少与其中一个值匹配,我认为它会像
if (x = any_of(1, 2 ,3)
// do something
但我在网上看到的例子是
bool any_of(InputIt first, InputIt last, UnaryPredicate)
那是什么意思?
C ++的新手,所以如果这是一个愚蠢的问题,请道歉。
有很多关于"C++迭代器">主题的文献和视频教程,你应该朝这个方向做一些研究,因为它是C++的基本概念。
关于这个问题的快速总结:迭代器是指向值集合(或范围(中的元素的东西。此类集合的几个示例:
std::vector
是最常见的一种。它基本上是一个可调整大小的数组。std::list
是一个链表。std::array
是一个固定大小的数组,在C样式数组周围有一些很好的助手int myInt[12]
是一个 C 样式的整数数组。这个不应该再用了。
C++标准库中对值集合(如std::any_of
(进行操作的算法通过两个迭代器获取集合。第一个迭代器InputIt first
指向所述集合的开头,而InputIt last
指向集合的末尾(实际上是结束之后的一个(。
UnaryPredicate
是一个接受 1 个参数(一元(并返回布尔值(谓词(的函数。
为了让std::any_of
做你想做的事,你必须把你的值放在一个集合中,x
UnaryPredicate
:
int x = 3;
std::vector values = {1, 2, 3};
if (std::any_of(values.begin(), values.end(), [x](int y) { return x == y; }))
// ...
本例中的UnaryPredicate
是 lambda 函数。
如您所见,根据您的示例,这是非常冗长的代码。但是,一旦你有一个想要比较的动态值堆积,或者你想检查比相等更复杂的事情,这个算法就会变得更加有益。
有趣的小实验
只是为了好玩,我做了一个小的代码片段来实现你想要的any_of
。这是相当多的代码和相当复杂的(绝对不是初学者水平!(,但它非常灵活,实际上很好用。完整的代码可以在这里找到。
以下是您将如何使用它:
int main()
{
int x = 7;
std::vector dynamic_int_range = {1, 2, 3, 4, 5, 6, 7, 8};
if (x == any_of(1, 2, 3, 4, 5))
{
std::cout << "x is in the compile time collection!n";
}
else if (x == any_of(dynamic_int_range))
{
std::cout << "x is in the run time collection!n";
}
else
{
std::cout << "x is not in the collection :(n";
}
std::string s = "abc";
std::vector<std::string> dynamic_string_range = {"xyz", "uvw", "rst", "opq"};
if (s == any_of("abc", "def", "ghi"))
{
std::cout << "s is in the compile time collection!n";
}
else if (s == any_of(dynamic_string_range))
{
std::cout << "s is in the run time collection!n";
}
else
{
std::cout << "s is not in the collection :(n";
}
}
以下是它的实现方式:
namespace detail
{
template <typename ...Args>
struct ct_any_of_helper
{
std::tuple<Args...> values;
constexpr ct_any_of_helper(Args... values) : values(std::move(values)...) { }
template <typename T>
[[nodiscard]] friend constexpr bool operator==(T lhs, ct_any_of_helper const& rhs) noexcept
{
return std::apply([&](auto... vals) { return ((lhs == vals) || ...); }, rhs.values);
}
};
template <typename Container>
struct rt_any_of_helper
{
Container const& values;
constexpr rt_any_of_helper(Container const& values) : values(values) { }
template <typename T>
[[nodiscard]] friend constexpr bool operator==(T&& lhs, rt_any_of_helper&& rhs) noexcept
{
return std::any_of(cbegin(rhs.values), cend(rhs.values), [&](auto val)
{
return lhs == val;
});
}
};
template <typename T>
auto is_container(int) -> decltype(cbegin(std::declval<T>()) == cend(std::declval<T>()), std::true_type{});
template <typename T>
std::false_type is_container(...);
template <typename T>
constexpr bool is_container_v = decltype(is_container<T>(0))::value;
}
template <typename ...Args>
[[nodiscard]] constexpr auto any_of(Args&&... values)
{
using namespace detail;
if constexpr (sizeof...(Args) == 1 && is_container_v<std::tuple_element_t<0, std::tuple<Args...>>>)
return rt_any_of_helper(std::forward<Args>(values)...);
else
return ct_any_of_helper(std::forward<Args>(values)...);
}
如果专家看到这段代码并想抱怨悬而未决的引用:来吧,谁会写这样的东西:
auto a = any_of(std::array {1, 2, 3, 4});
if (x == std::move(a)) // ...
这不是这个函数的用途。
您的值必须已经存在于其他地方,它很可能是一个向量。
std::any_of
在迭代器上运行。
C++中的迭代器是范围,这两个值告诉您范围的开始位置和结束位置。
大多数C++标准模板库集合(包括std::vector
(都支持迭代器 API,因此您可以在它们上使用std::any_of
。
为了一个完整的示例,让我们检查一个向量是否包含42
在顶部方式,只是为了使用std::any_of
.
由于我们只想检查向量中的值是否存在而不更改任何内容(std::any_of
不会修改集合(,因此我们使用返回constant
begin
vector
的end
.cbegin()
和.cend()
,这些对std::any_of
很重要,因为它必须遍历整个向量以检查是否至少有一个值与给定谓词匹配。
最后一个参数必须是一元谓词,这意味着它是一个函数,接受单个参数,并返回给定参数是否符合某些条件。
简而言之,std::any_of
用于检查集合中是否至少有一个值,该值具有您关心的某些属性。
法典:
#include <algorithm>
#include <iostream>
#include <vector>
bool is_42(int value) {
return value == 42;
}
int main() {
std::vector<int> vec{
1, 2, 3,
// 42 // uncomment this
};
if(std::any_of(vec.cbegin(), vec.cend(), is_42)) {
std::cout << "42 is in vec" << std::endl;
} else {
std::cout << "42 isn't in vec" << std::endl;
}
}
正如用户@a.abuzaid所述,您可以为此创建自己的方法。然而,他们提供的方法在答复的评论中陈述的一些方面有所欠缺。到目前为止,我真的无法理解std::any_of
,只是决定创建这个模板:
template <typename Iterable, typename type>
bool any_of(Iterable iterable, type value) {
for (type comparison : iterable) {
if (comparison == value) {
return true;
}
}
return false;
}
这里使用的示例是if (any_of(myVectorOfStrings, std::string("Find me!"))) { do stuff }
,其中iterable
是字符串的向量,value
是字符串"找到我!
您可以创建一个函数,将x与其他两个数字进行比较,以检查它们是否相同
bool anyof(int x, int y, int z) {
if ((x == y) || (x == z))
return true;
}
然后在主函数中,您可以像这样调用函数:
if (anyof(x, 1, 2))
cout << "Matches a number";
- Usages of std::move
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 具有变量Number of Arguments的std::函数的矢量
- Capacity of a deque
- 哪些类型可以转换为std::any
- Deprecation of _writeBarrier()
- constexpr begin of a std::array
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- C++ "error: invalid use of void expression"
- 我看到"use of undeclared identifier"错误,有人可以告诉我如何解决它吗?
- 赛通"Cannot take address of memoryview slice"
- C++ Version Of Double.longBitsToDouble
- 收到错误"invalid use of non-static data member 'stu::n' "
- C++ Usage of AsyncCallback
- 错误:"Left of getValue must have class/struct/union"
- Centos7 g++ "to_string is not in a member of std"
- 解决方法:"out of line definition of 'graph' does not match any declaration in 'graph'"
- "local variables at the outermost scope of the function may not use the same name as any parameter"是
- 如何将"Any kind of data"传递给 C++ 中的函数