C ++:队列包装器模板问题

时间:2017-07-28 18:28:18

标签: c++11 queue std mutex

简短问题:我在 SafeQueue :: clear()中使用std::is_pointer和/或std::is_array犯了什么明显错误(误解?) ?目的是检查指针队列,然后检查指针是否恰好是unsigned char*char*数组。

这是在C ++ 11中,包含std::queue类以带来接近线程安全的东西。

#ifndef SAFEQUEUE_H
#define SAFEQUEUE_H

#include <queue>
#include <mutex>
#include <type_traits>

template <typename T>
class SafeQueue
{
    public:
        SafeQueue() = default; // default ctor
        SafeQueue(const SafeQueue&) = delete; // disable copy
        SafeQueue& operator=(const SafeQueue&) = delete; // disable assignment

        bool empty() const
        {
            std::unique_lock<std::mutex> ulock(m_mutex);
            return m_queue.empty();
        }

        T& front() // never called without empty() or size() > 0 check
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            if(!m_queue.empty()) { return m_queue.front(); }
        }

        void clear()
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            if(m_queue.empty()) { return; } // quick exit

            bool isPointers = (std::is_pointer<T>::value) ? true : false; // always returns true on class objects
            if(isPointers)
            {
                //bool isarray = std::is_array<T>::value ? true : false; // always returns true on class objects
                bool isarray = (std::is_same<unsigned char*, T>::value || std::is_same<char*, T>::value) ? true : false; // also returns true always
                while(!m_queue.empty())
                {
                    if(isarray) { delete[] m_queue.front(); m_queue.front() = nullptr; }
                    else { delete[] m_queue.front(); m_queue.front() = nullptr; }
                    m_queue.pop();
                }
            }
            else { std::queue<T>().swap(m_queue); }
        }

        void pop()
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            if(!m_queue.empty()) { m_queue.pop(); }
        }

        unsigned int size() const
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            return m_queue.size();
        }

        void push(const T& item)
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_queue.push(item);
        }

    protected:
        mutable std::mutex m_mutex;
        std::queue<T> m_queue;
};

#endif // SAFEQUEUE_H

1 个答案:

答案 0 :(得分:1)

即使控件为false,也会编译所有分支。

您正在获取构建中断,因为对于T=intdelete[]上调用的int不是合法的C ++。

解决问题的方法是不存储原始char*数组,而是存储队列中的std::unique_ptr<char[]>std::unique_ptr<unsigned char[]>等智能指针。

您可以使用类型特征执行此操作:

template<class T> struct queued_type{
  using type=T;
  using extracted_type=T&;
  static extracted_type extract(type& out){ return out; }
  static type& box(T& in){ return in; }
};
template<class T> struct queued_type<T*>{
  using type=std::unique_ptr<T[]>;
  using extracted_type=type;
  static extracted_type extract(type& out){ return out.release(); }
  static type box(type& in){ return type(in); }
};
template<class T>using queued_type_t=typename queued_type<T>::type;

现在存储std::queue<queued_type_t<T>>push m_queue.push(queued_type<T>::box(in));front执行queued_type<T>::extract(m_queue.front())并返回typename queued_type<T>::extracted_type

明确是std::queue<queued_type_t<T>>{}.swap(m_queue);没有逻辑。