概述
我正在用 C 實作一個生產者-消費者模型。我有多個消費者,每個消費者都有自己的執行緒和佇列。為了方便訪問,我想要一個表單 <ID,消費者實體> 的映射,以便我可以在將資料推送到消費者執行緒時通過查找簡單地獲取消費者執行緒。嘗試訪問存盤的實體方法時,編譯器會拋出錯誤。
代碼
消費者類啟動一個帶有附加 FIFO 佇列的執行緒,并等待專案被推入(佇列頭可在此處獲得:https : //github.com/cameron314/readerwriterqueue/blob/master/readerwriterqueue.h)
// consumer.h
#include <functional>
#include <thread>
#include "readerwriterqueue.h"
// TYPE HAS TO BE A POINTER
template<typename T>
class Consumer
{
public:
Consumer(int id, std::function<void(int, T&)> func) :
m_id(id), m_func(func) {}
~Consumer(){
m_running = false;
this->pushBack(nullptr);
m_thread.join();
}
// satisfy rule of three; disallow copying as we manage a thread
Consumer(const Consumer&) = delete;
Consumer& operator=(const Consumer&) = delete;
void pushBack(const T& t){
m_BufferQueue.enqueue(t);
}
private:
void work() {
m_running = true;
while(m_running || m_BufferQueue.peek())
{
T t;
m_BufferQueue.wait_dequeue(t);
if (t == nullptr)
break;
m_func(m_id, t);
}
}
int m_id;
std::function<void(int, T&)> m_func;
moodycamel::BlockingReaderWriterQueue<T> m_BufferQueue{64};
std::thread m_thread{&Consumer::work, this};
std::atomic_bool m_running;
};
我想創建這個類的多個實體并將它們放入一個無序映射中,這樣我就可以在必要時推送到它們的佇列中。據我所知,emplace 幫助我避免撰寫移動建構式/賦值運算子,因為它直接創建物件并將其放置在地圖中。
// main_player.cpp
#include <iostream>
#include <unordered_map>
#include "consumer.h"
void func(int id, int* val)
{
std::cout << "Thread " << id << " received value " << *val << "\n";
}
int main(int argc, char** argv) {
std::unordered_map<int, Consumer<int*>> consumers;
consumers.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple(0, func));
// push into queues here and let the threads do the work
for(int i = 0; i < 5; i )
consumers[0].pushBack(&i)
return 0;
}
編譯器在將 pushBack 推入佇列時出現問題。從錯誤日志中,我可以推斷出他似乎確實構造了另一個實體并且失敗了。有人可以幫我嗎?
錯誤日志
In file included from /usr/include/c /7/functional:54:0,
from ../consumer.h:4,
from ../main_player.cpp:31:
/usr/include/c /7/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {int&&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const int; _T2 = Consumer<int*>]’:
/usr/include/c /7/tuple:1641:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {int&&}; _Args2 = {}; _T1 = const int; _T2 = Consumer<int*>]’
/usr/include/c /7/ext/new_allocator.h:136:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, Consumer<int*> >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::pair<const int, Consumer<int*> >]’
/usr/include/c /7/bits/alloc_traits.h:475:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, Consumer<int*> >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::pair<const int, Consumer<int*> >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::pair<const int, Consumer<int*> > >]’
/usr/include/c /7/bits/hashtable_policy.h:2066:37: required from ‘std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, Consumer<int*> >, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const int, Consumer<int*> >, false>]’
/usr/include/c /7/bits/hashtable_policy.h:750:8: required from ‘std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type& std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::operator[](std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type&&) [with _Key = int; _Pair = std::pair<const int, Consumer<int*> >; _Alloc = std::allocator<std::pair<const int, Consumer<int*> > >; _Equal = std::equal_to<int>; _H1 = std::hash<int>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type = Consumer<int*>; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type = int]’
/usr/include/c /7/bits/unordered_map.h:977:20: required from ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type&&) [with _Key = int; _Tp = Consumer<int*>; _Hash = std::hash<int>; _Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, Consumer<int*> > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = Consumer<int*>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = int]’
../main_player.cpp:48:20: required from here
/usr/include/c /7/tuple:1652:70: error: no matching function for call to ‘Consumer<int*>::Consumer()’
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from ../main_player.cpp:31:0:
../consumer.h:13:5: note: candidate: Consumer<T>::Consumer(int, std::function<void(int, T&)>) [with T = int*]
Consumer(int id, std::function<void(int, T&)> func) :
^~~~~~~~
../consumer.h:13:5: note: candidate expects 2 arguments, 0 provided
make: *** [main_player.o] Error 1
subdir.mk:66: recipe for target 'main_player.o' failed
"make -j20 all" terminated with exit code 2. Build might be incomplete.
18:01:03 Build Failed. 3 errors, 0 warnings. (took 739ms)
uj5u.com熱心網友回復:
您需要在類中添加默認建構式,Consumer如錯誤所述
error: no matching function for call to ‘Consumer<int*>::Consumer()’
您可以通過兩種方式執行此操作:
方法一
// consumer.h
#include <functional>
#include <thread>
#include "readerwriterqueue.h"
// TYPE HAS TO BE A POINTER
template<typename T>
class Consumer
{
public:
Consumer(int id, std::function<void(int, T&)> func) :
m_id(id), m_func(func) {}
//other member here
//ADD THE DEFAULT CONSTRUCTOR
Consumer() = default;
private:
//...
int m_id = 0; //USE IN-CLASS INITIALIZER for built in type
//other members here
};
方法二
// consumer.h
#include <functional>
#include <thread>
#include "readerwriterqueue.h"
// TYPE HAS TO BE A POINTER
template<typename T>
class Consumer
{
public:
Consumer(int id, std::function<void(int, T&)> func) :
m_id(id), m_func(func) {}
//other member here
//ADD THE DEFAULT CONSTRUCTOR
Consumer(): m_id(0)
{
}
private:
//...
int m_id;
//other members here
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/382475.html
上一篇:如何旋轉四邊形
