此代码是从以下link
中引用的我真的无法确定该错误并第一次看到它
整个代码
#include <boost/thread/thread.hpp>
#include <boost/lockfree/queue.hpp>
#include <iostream>
#include <queue>
#include <boost/atomic.hpp>
template<typename QueueContents, template<typename QueueContents> class QueueType>
class WorkerThread
{
public:
WorkerThread(QueueType<QueueContents> &Queue, int NoOfIt, int Delay)
: m_Queue(Queue) // queue shared with consumer
, m_Delay(Delay) // delay for simulating heavy work
, m_NoOfIt(NoOfIt) // number of work items to produce
{}
void Start() // start work
{
m_Thread = boost::thread(&WorkerThread::Work, this);
}
void Stop() // interrupt work
{
m_Thread.interrupt();
}
virtual void Work() = 0;
void WaitUntilFinished()
{
m_Thread.join();
}
protected:
int m_NoOfIt;
int m_Delay;
QueueType<QueueContents> &m_Queue;
private:
boost::thread m_Thread;
};
template<typename QueueContents, template<typename QueueContents> class QueueType>
class Producer : public WorkerThread<QueueContents, QueueType>
{
public:
Producer(QueueType<QueueContents> &Queue, int NoOfIt, int Delay)
: WorkerThread<QueueContents, QueueType>(Queue, NoOfIt, Delay)
{}
void Work()
{
for (QueueContents i=0; i < this->m_NoOfIt; ++i)
{
// send numbers 0 to 999 into the queue
boost::this_thread::sleep(boost::posix_time::milliseconds(this->m_Delay));
std::ostringstream msg;
msg << "[PRODUCER] Produced value " << i << std::endl;
std::cout << msg.str();
this->m_Queue.Push(i);
}
}
};
// New BSD License
class ResetableEvent
{
bool m_EventStatus;
bool m_AutoResetEvent;
boost::condition_variable m_Signal;
boost::mutex m_Mutex;
public:
explicit ResetableEvent(bool _auto_reset = false)
: m_EventStatus(false)
, m_AutoResetEvent(_auto_reset)
{}
void wait() // wait for event
{
boost::unique_lock<boost::mutex> lock(m_Mutex);
if (m_EventStatus)
{
if (m_AutoResetEvent)
m_EventStatus = false;
return;
}
do
{
m_Signal.wait(lock);
} while(!m_EventStatus);
if (m_AutoResetEvent)
m_EventStatus = false;
}
void set() // this notifies threads waiting for this event
// and makes sure that other threads about to wait
// can immediately proceed
{
boost::lock_guard<boost::mutex> lock(m_Mutex);
m_EventStatus = true;
m_Signal.notify_one();
}
void reset() // reset event: threads who will wait for this
// event will be blocked
{
boost::lock_guard<boost::mutex> lock(m_Mutex);
m_EventStatus = false;
}
};
// Queue class that can be used in multithreading context
template <typename T>
class BoundedThreadSafeQueueSignalWorkloadDone
{
private:
std::queue<T> m_queue; // Use STL queue to store data
boost::mutex m_mutex; // The mutex to synchronise on
boost::condition_variable m_QueueHasData; // The condition to wait for if queue is empty
boost::condition_variable m_QueueHasRoom; // The condition to wait for if queue is full
ResetableEvent m_ProcessingDone; // The conditon to wait for if queue is empty
// and workload is fully processed
unsigned int m_Size; // max queue size
public:
BoundedThreadSafeQueueSignalWorkloadDone(unsigned int Size)
: m_Size(Size)
{
m_ProcessingDone.set();
}
bool Empty()
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
return m_queue.empty();
}
bool Full()
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
return m_queue.size() >= m_Size;
}
// Push new data on the queue and notify other threads
// waiting for data in this queue
bool TryPush(const T &data)
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
// Indicate that workload processing is busy
// Fail if queue full
if (m_queue.size() >= m_Size) return false;
// Indicate that workload is being processed
m_ProcessingDone.reset();
// Add the data to the queue
m_queue.push(data);
// Notify others that data is ready
m_QueueHasData.notify_one();
return true;
} // Lock is automatically released here
// Try to push data in queue
// Wait until room in queue
void Push(const T &data)
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
// While queue is full, wait
// warning: do not replace m_queue.size() == m_Size with Full():
// it will deadlock due to trying to acquire the same m_mutex
// Push has already acquired
while (m_queue.size() >= m_Size) m_QueueHasRoom.wait(lock);
// Indicate that workload is being processed
m_ProcessingDone.reset();
// Now push the data
m_queue.push(data);
// And warn threads that are waiting for data
m_QueueHasData.notify_one();
}
// Get data from the queue.
// Return false if no data available
bool TryPop(T &result)
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
// When there is no data, return false
if (m_queue.size() == 0) return false;
// Otherwise return the data
// Retrieve the data from the queue
result=m_queue.front(); m_queue.pop();
// Warn threads who are waiting to push data
m_QueueHasRoom.notify_one();
return true;
// Lock is automatically released here
}
// Get data from the queue.
// Wait for data if not available
void WaitAndPop(T &result)
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
// When there is no data, wait till someone fills it.
// Lock is automatically released in the wait and obtained
// again after the wait
while (m_queue.size() == 0) m_QueueHasData.wait(lock);
// Retrieve the data from the queue
result=m_queue.front(); m_queue.pop();
// Warn threads who are waiting to push data
m_QueueHasRoom.notify_one();
} // Lock is automatically released here
void ProcessingFinished()
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
// If no new work scheduled,
// we can signal the queue as completely idle
if (m_queue.empty())
m_ProcessingDone.set();
else
std::cout << "[QUEUE] ProcessingFinished but queue not empty. ProcessingDone flag remains low." << std::endl;
}
void WaitUntilCompletelyIdle()
{
std::cout << "[QUEUE] Wait until idle" << std::endl;
m_ProcessingDone.wait();
std::cout << "[QUEUE] Consumer is completely idle" << std::endl;
}
};
template<typename QueueContents, template<typename QueueContents> class QueueType>
class Producer : public WorkerThread<QueueContents, QueueType>
{
public:
Producer(QueueType<QueueContents> &Queue, int NoOfIt, int Delay)
: WorkerThread<QueueContents, QueueType>(Queue, NoOfIt, Delay)
{}
void Work()
{
for (QueueContents i=0; i< this->m_NoOfIt; ++i)
{
// send numbers 0 to 999 into the queue
boost::this_thread::sleep(boost::posix_time::milliseconds(this->m_Delay));
std::ostringstream msg;
msg << "[PRODUCER] Produced value " << i << std::endl;
std::cout << msg.str();
this->m_Queue.Push(i);
}
}
};
template<typename QueueContents, template<typename QueueContents> class QueueType>
class Consumer : public WorkerThread<QueueContents, QueueType>
{
public:
Consumer(QueueType<QueueContents> &Queue, int NoOfIt, int Delay)
: WorkerThread<QueueContents, QueueType>(Queue, NoOfIt, Delay)
{}
void Work()
{
for (QueueContents i=0; i< this->m_NoOfIt; ++i)
{
// read data from the queue,
// waiting until data available
int num = -1;
this->m_Queue.WaitAndPop(num);
std::ostringstream msg;
msg << "[CONSUMER] Consumed value " << num << std::endl;
std::cout << msg.str();
boost::this_thread::sleep(boost::posix_time::milliseconds(this->m_Delay)); // work hard
this->m_Queue.ProcessingFinished(); // tell the queue we're done working hard
std::ostringstream msg2;
msg2 << "[CONSUMER] Consumption of value " << num << " completely handled." << std::endl;
std::cout << msg2.str();
}
}
};
int main()
{
std::cout << "[MAIN] About to construct queue" << std::endl;
BoundedThreadSafeQueueSignalWorkloadDone<int> Q(3);
std::cout << "[MAIN] About to construct producer" << std::endl;
Producer<int, BoundedThreadSafeQueueSignalWorkloadDone> P(Q, 10, 0);
std::cout << "[MAIN] About to construct consumer" << std::endl;
Consumer<int, BoundedThreadSafeQueueSignalWorkloadDone> C(Q, 10, 100);
std::cout << "[MAIN] About to start producer" << std::endl;
P.Start();
std::cout << "[MAIN] About to start consumer" << std::endl;
C.Start();
for (unsigned int i=0; i<20;++i)
{
C.WaitUntilCompletelyIdle();
boost::this_thread::sleep(boost::posix_time::milliseconds(2));
}
std::cout << "[MAIN] Queue should be empty after all threads finished: " << Q.Empty() << std::endl;
std::cout << "[MAIN] Waiting for producer to finish" << std::endl;
P.WaitUntilFinished();
std::cout << "[MAIN] Waiting for consumer to finish" << std::endl;
C.WaitUntilFinished();
return 0;
}
错误
main.cpp:6:43: error: declaration of template parameter ‘QueueContents’ shadows template parameter template<typename QueueContents, template<typename QueueContents> class QueueType>
答案 0 :(得分:1)
该代码是错误的,它违反了规则[temp.local]/6,该规则禁止将模板参数名称用于任何其他目的。
不得在其范围(包括嵌套范围)内重新声明 template-parameter 。
作者可能使用了GCC 5,它没有实现该规则,但是自从GCC 6开始就实现了。
Live demo
作为快速解决方案,只需删除模板模板参数名称。还是不使用。
var obj = {
"2019-04-02T00:00:00-04:00": {
"2019-04-02T09:00:00-04:00": {
"2019-04-02T18:00:00-04:00": {
"[MET] L2 - NB": {
"attendees": [
"Lex Luthor",
"Lois Lane"
]
},
"[MET] L2 - CS": {
"attendees": [
"General Zod",
"Clark Kent"
]
}
}
}
},
"2019-04-03T00:00:00-04:00": {
"2019-04-03T09:00:00-04:00": {
"2019-04-03T18:00:00-04:00": {
"[MET] L2 - NB": {
"attendees": [
"Lex Luthor",
"Lois Lane"
]
},
"[MET] L2 - CS": {
"attendees": [
"General Zod",
"Clark Kent"
]
}
}
}
}
}
const res = [];
Object.entries(obj).forEach(([date, value]) => {
Object.entries(value).forEach(([start, value2]) => {
Object.entries(value2).forEach(([end, value3]) => {
Object.entries(value3).forEach(([label, value4]) => {
res.push({
Date: date,
StartTimeLocalized: start,
EndTimeLocalized: end,
LabelWithCompany: label,
attendees: value4.attendees
})
})
})
})
})
console.log(res)