2017-07-28 1 views
0

Kurze Frage: Welche offensichtlichen Fehler (Missverständnis?) Bin ich mit der Verwendung von std::is_pointer Herstellung und/oder std::is_array innerhalb SafeQueue :: clear()? Die Absicht ist, nach einer Schlange von Zeigern zu suchen, dann zu überprüfen, ob Zeiger zufällig unsigned char* oder char* sind.C++: Queue Wrapper Probleme mit Vorlagen

Dies ist in C++ 11, wickeln die std::queue Klasse, um etwas Näherung Fadensicherheit zu bringen.

#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 
+0

Woher wissen Sie, dass diese Zeilen "immer wahr" zurückgegeben werden? Welches tatsächliche spezifische Verhalten lässt Sie das denken? [MCVE] bedeutet * enthält ein spezifisches Problem oder einen Fehler *; Ihre Interpretation, warum dieser Fehler auftritt, reicht nicht aus. – Yakk

Antwort

1

Alle Niederlassungen sind zusammengestellt, auch wenn die Steuerung false ist.

Sie erhalten Build-Pausen, weil für T=int, delete[] angerufen int ist nicht legal C++.

Der Weg, um Ihr Problem zu beheben, ist nicht Arrays von rohen char*, sondern Smart-Pointer wie std::unique_ptr<char[]> oder std::unique_ptr<unsigned char[]> in Ihrer Warteschlange zu speichern.

Sie können diese Eigenschaft mit einer Art tun:

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; 

Jetzt eine std::queue<queued_type_t<T>> speichern. push tut eine m_queue.push(queued_type<T>::box(in));, front tut eine queued_type<T>::extract(m_queue.front()) und gibt eine typename queued_type<T>::extracted_type zurück.

Und klar ist std::queue<queued_type_t<T>>{}.swap(m_queue); ohne Logik.