C++ 初学者如何使用std::any_?

C++ 初学者如何使用std::any_?,c++,C++,我想将一个值与其他几个值进行比较,并检查它是否至少与其中一个值匹配,我假设它是 if (x = any_of(1, 2 ,3) // do something 但我在网上看到的例子是 bool any_of(InputIt first, InputIt last, UnaryPredicate) 这是什么意思 C++,如果这是一个愚蠢的问题,请道歉。< /P> < P>你可以创建一个函数,在这里你将X和其他两个数字进行比较,以检查它们是否相同,例如 bool anyof(int x,

我想将一个值与其他几个值进行比较,并检查它是否至少与其中一个值匹配,我假设它是

if (x = any_of(1, 2 ,3)
   // do something
但我在网上看到的例子是

bool any_of(InputIt first, InputIt last, UnaryPredicate)
这是什么意思


<新> C++,如果这是一个愚蠢的问题,请道歉。< /P> < P>你可以创建一个函数,在这里你将X和其他两个数字进行比较,以检查它们是否相同,例如

bool anyof(int x, int y, int z) {
    if ((x == y) || (x == z))
        return true;
}
然后在main中,您可以调用如下函数:

if (anyof(x, 1, 2))
    cout << "Matches a number";
auto a = any_of(std::array {1, 2, 3, 4});
if (x == std::move(a)) // ...
if(任意(x,1,2))

cout这不是这个函数的用途

您的值必须已经存在于其他地方,它很可能是一个向量

对迭代器进行操作

C++中的迭代器是两个值,它们告诉你开始的位置,以及结束的范围。

大多数C++标准模板库集合,包括<>代码> STD::vector < /C> >,支持迭代器API,因此可以使用<代码> STD::YANYO<<代码> >

为了获得完整的示例,让我们检查向量是否包含
42
,只需使用
std::any_of

由于我们只想检查向量中的值是否存在,而不改变任何内容(
std::any_of
不会修改集合),因此我们使用
.cbegin()
.cend()
返回
常量
向量的
开始
结束
,这对
std::any_of
非常重要,因为它必须遍历整个向量,以检查是否至少有一个值与给定谓词匹配

最后一个参数必须是一元谓词,这意味着它是一个函数,接受单个参数,并返回给定参数是否符合某些条件

简单地说,
std::any_of
用于检查集合中是否至少有一个值,该值具有您关心的属性

代码:

#包括
#包括
#包括
布尔值为42(整数值){
返回值==42;
}
int main(){
向量向量{
1, 2, 3,
//42//取消对此的注释
};
if(std::任意(vec.cbegin(),vec.cend(),is_42))的{

STD::CUT> P.>关于“C++中迭代器”的主题有很多文献和视频教程,你应该在那个方向做一些研究,因为它是C++中的一个基本概念。 简单总结一下:迭代器是指值集合(或范围)中的元素。此类集合的几个示例:

  • std::vector
    是最常见的。它基本上是一个可调整大小的数组
  • std::list
    是一个链接列表
  • std::array
    是一个固定大小的数组,在C样式数组周围有一些很好的助手
  • int-myInt[12]
    是一个C风格的整数数组。这个数组不应该再使用了
< P>从C++标准库中执行的算法,它对值集合(如<代码> STD::YANYO >)采用两个迭代器进行集合。第一个迭代器<代码>第一个< /代码>指向集合的开头,而<>代码> InputIt最后< /C> >指向集合的末尾(实际上是一个结束)。
一元谓词
是一个接受1个参数(一元)并返回bool(谓词)的函数

为了让
std::任意
做你想做的事,你必须把你的值放在一个集合中,把
x
放在
一元谓词中

int x = 3;
std::vector values = {1, 2, 3};
if (std::any_of(values.begin(), values.end(), [x](int y) { return x == y; }))
    // ...
本例中的
一元谓词
是一个lambda函数

正如您所看到的,给出您的示例,这是一段非常详细的代码。但是,一旦您有了一个动态的要比较的值集合,或者您想要检查比相等更复杂的东西,这个算法就会变得更加有用

有趣的小实验 为了好玩,我制作了一个小代码片段,它实现了一个你想要的
任何
。它的代码相当多,也相当复杂(绝对不是初学者!),但它非常灵活,而且使用起来非常好。可以找到完整的代码

以下是您将如何使用它:

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";
    }    
}

这不是一个愚蠢的问题,但正确回答它基本上是一本学习手册的两章。现在,你应该坚持使用逻辑OR运算符
|
。你的函数有未定义的行为,因为它不会在所有执行路径上返回值。我还怀疑这个函数是否非常有用,因为它只与
int一起工作s,并且仅当有两个要比较时才使用。只需使用
if((x==y)| |(x==z))
直接在需要的地方使用它似乎更直接。
返回x==y | | x==z;
。虽然变量参数模板和折叠表达式更通用、更有用……有没有一种方法可以将其扩展到大量变量?@baguettio我做了一些更新,只是作为概念证明(这样你就能看到C++的力量了)。
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)) // ...