使用现代 C++ 多线程惯用查找字符串中的第一个子字符串
Multithreaded idiomatic find first of substrings in a string using modern C++
使用 set::find
可以很容易地在一组字符串中找到一个字符串,或者使用 std::find_first_of
可以很容易地找到一组字符串中的第一个字符串。但我认为 STL 不处理字符串中 find_first_of 组字符串(子字符串)的这种情况。出于低延迟的原因,我使用并行执行,如果这个实现是使用现代 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){
//
// Maybe after launching 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.");
}
我认为惯用的方法是使用 std::find_if
。那么你也不需要 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;
}
);
}
如果你真的只想要 bool
你可以使用 std::any_of
:
bool find(const std::string & sentence)
{
return std::any_of( 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::vector
而不是 std::list
。 vector
s 提供随机访问迭代器,而 list
s 仅提供双向迭代器。
使用 set::find
可以很容易地在一组字符串中找到一个字符串,或者使用 std::find_first_of
可以很容易地找到一组字符串中的第一个字符串。但我认为 STL 不处理字符串中 find_first_of 组字符串(子字符串)的这种情况。出于低延迟的原因,我使用并行执行,如果这个实现是使用现代 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){
//
// Maybe after launching 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.");
}
我认为惯用的方法是使用 std::find_if
。那么你也不需要 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;
}
);
}
如果你真的只想要 bool
你可以使用 std::any_of
:
bool find(const std::string & sentence)
{
return std::any_of( 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::vector
而不是 std::list
。 vector
s 提供随机访问迭代器,而 list
s 仅提供双向迭代器。