C++:模板的队列包装器问题
C++: Queue wrapper issues with templates
小问题:我在 [=] 中使用 std::is_pointer
and/or std::is_array
犯了什么明显的错误(误解?) 20=]SafeQueue::clear()?目的是检查指针队列,然后检查指针是否恰好是 unsigned char*
或 char*
数组。
这是在 C++11 中,包装 std::queue
class 以带来接近线程安全的东西。
#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
即使控件是false
,也会编译所有分支。
您正在获取构建中断,因为对于 T=int
,delete[]
调用 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())
,returns 做 typename queued_type<T>::extracted_type
.
清楚的是std::queue<queued_type_t<T>>{}.swap(m_queue);
没有逻辑。
小问题:我在 [=] 中使用 std::is_pointer
and/or std::is_array
犯了什么明显的错误(误解?) 20=]SafeQueue::clear()?目的是检查指针队列,然后检查指针是否恰好是 unsigned char*
或 char*
数组。
这是在 C++11 中,包装 std::queue
class 以带来接近线程安全的东西。
#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
即使控件是false
,也会编译所有分支。
您正在获取构建中断,因为对于 T=int
,delete[]
调用 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())
,returns 做 typename queued_type<T>::extracted_type
.
清楚的是std::queue<queued_type_t<T>>{}.swap(m_queue);
没有逻辑。