c++11 - C++: Queue wrapper issues with templates -


short question: obvious mistake (misunderstanding?) making use of std::is_pointer and/or std::is_array within safequeue::clear()? intent check queue of pointers, check if pointers happen unsigned char* or char* arrays.

this in c++11, wrapping std::queue class bring approaching thread safety.

#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; // returns true on class objects             if(ispointers)             {                 //bool isarray = std::is_array<t>::value ? true : false; // returns true on class objects                 bool isarray = (std::is_same<unsigned char*, t>::value || std::is_same<char*, t>::value) ? true : false; // returns true                 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 

all branches compiled if control false.

you getting build breaks because t=int, delete[] called on int not legal c++.

the way fix problem not store arrays of raw char*, instead smart pointers std::unique_ptr<char[]> or std::unique_ptr<unsigned char[]> in queue.

you can type trait:

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; 

now store std::queue<queued_type_t<t>>. push m_queue.push(queued_type<t>::box(in));, front queued_type<t>::extract(m_queue.front()) , returns typename queued_type<t>::extracted_type.

and clear std::queue<queued_type_t<t>>{}.swap(m_queue); no logic.


Comments