简体   繁体   English

多线程惯用语使用现代 C++ 查找字符串中的第一个子字符串

[英]Multithreaded idiomatic find first of substrings in a string using modern C++

It is easy to find a string in a set of strings using set::find or first of a set of strings in a set of strings using std::find_first_of.使用 set::find 或使用 std::find_first_of 查找一组字符串中的第一个字符串很容易。 But I think that STL doesn't handle this case of find_first_of set of strings (substrings) in a string.但我认为 STL 不能处理字符串中 find_first_of 字符串集(子字符串)的这种情况。 For low latency reason I use parallel execution, would you please let me know if this implementation is idiomatic using modern C++ :出于低延迟的原因,我使用并行执行,请让我知道此实现是否符合使用现代 C++ 的习惯:

#include <string>
#include <list>
#include <atomic>
#include <execution>
#include <iostream>

class Intent{
    const std::list<std::string> m_Context;
    const std::string m_Name;
    std::atomic_bool m_Found;
public:
    Intent(const std::list<std::string> context, const std::string name)
        : m_Context(context)
        , m_Name(name)
        , m_Found(false)
        {}
    Intent(const Intent & intent) = delete;
    Intent & operator=(const Intent & intent) = delete;
    Intent(Intent && intent) : m_Context(std::move(intent.m_Context))
                    , m_Name(std::move(intent.m_Name))
                    , m_Found(static_cast< bool >(intent.m_Found))
                    {}

    bool find(const std::string & sentence)
    {
        for_each( std::execution::par
                , std::begin(m_Context)
                , std::end(m_Context)
                , [& m_Found = m_Found, & sentence](const std::string & context_element){
                    //
                    // May be after lauching thread per context_element one of them make intent Found
                    // so no need to run string::find in the remaining threads.
                    //
                    if(!m_Found){ 
                        if(sentence.find(context_element) != std::string::npos)
                        {
                            m_Found = true;
                        }
                    }
                }
            );
        return m_Found;
    }
    const bool getFound() const {return m_Found;}
    const std::string & getName() const {return m_Name;}
};

int main()
{
    Intent intent({"hello", "Hi", "Good morning"}, "GREETING");
    std::cout << intent.find("Hi my friend.");
}

I think the idiomatic way of doing it would be to use std::find_if .我认为这样做的惯用方法是使用std::find_if Then you don't need the atomic<bool> either.那么你也不需要atomic<bool>

// return iterator to found element or end()
auto find(const std::string & sentence)
{
    return std::find_if( std::execution::par
            , std::begin(m_Context)
            , std::end(m_Context)
            , [&sentence](const std::string & context_element) {
                return sentence.find(context_element) != std::string::npos;
            }
        );
}

If you really only want a bool :如果你真的只想要一个bool

bool find(const std::string & sentence)
{
    return std::find_if( std::execution::par
            , std::begin(m_Context)
            , std::end(m_Context)
            , [&sentence](const std::string & context_element) {
                return sentence.find(context_element) != std::string::npos;
            }
        ) != std::end(m_Context);
}

You may want to consider using a std::vector instead of a std::list too.您可能还想考虑使用std::vector而不是std::list vector s provide random access iterators while list s only provide bidirectional iterators. vector s 提供随机访问迭代器,而list s 只提供双向迭代器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM