参数“ QueueContents”阴影模板参数模板类QueueType

时间:2019-04-01 11:47:00

标签: c++ templates boost

此代码是从以下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>

1 个答案:

答案 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)