需要语法帮助以根据模板参数的类型专门化 class 方法
Need syntax help to specialize class methods based on type of template argument
我有一个通用的线程安全队列 class,它使用 std::priority_queue<std::shared_ptr<T>>
作为容器类型(通过模板参数指定)。但是,我想另外专门化它以使用更简单的 std::queue<std::shared_ptr<T>>
。不幸的是,这将意味着使用不同的技术来检索队列的最顶层元素(top()
代表 std::priority_queue<T>
或 front()
代表 std::queue<T>
)。我有一个 live coliru demo 显示了 priority_queue
类型的工作原型。但是,如果我尝试通过添加以下代码来使用 std::queue
:
我从编译器中得到预期的错误,指示 std::queue
没有 top()
方法。
我怀疑获得此权利的关键是对每个 wait_and_pop
方法使用 std::enable_if_t<T>
。我该怎么做?
编辑:感谢T.C的建议,我相信适用于 GCC 和 MSVC 的通用解决方案需要对 UtlThreadSafeQueue。有更新直播 coliru demo here:
// Note that overloading 2 function using expression SFINAE
// as shown here does not work on MSVC compiler - it does
// work on later builds of GCC though.
//template<class Q>
//auto front_or_top(Q& q) -> decltype(q.front()) {
// return q.front();
//}
//template<class Q>
//auto front_or_top(Q& q) -> decltype(q.top()) {
// return q.top();
//}
// this is a specific overload to work around the missing
// expression SFINAE in MSVC - for the std::queue<T>
template<class T>
auto front_or_top(std::queue<T>& q) -> decltype(q.front()) {
return q.front();
}
// this is a specific overload to work around the missing
// expression SFINAE in MSVC - for the std::priority_queue<T>
template<class T>
auto front_or_top(std::priority_queue<T>& q) -> decltype(q.top()) {
return q.top();
}
/**
* default type of container is a std::queue - which by default
* uses a std::deque<> of std::shared_ptr<T>'s. The default
* std::queue<T> does not need to order elements, and as
* such, it does not require an element comparator as is
* required by its priority queue counterpart.
*
* For the UtlThreadSafeQueue variant that uses a priority
* queue, we must define a comparator to compare
* <code>std::shared_ptr<T>'s</code>.
*
* To use a UtlThreadSafeQueue with a priority_queue container,
* use as follows:
*
* <pre>{@code
* // using priority queue
* UtlThreadSafeQueue<PriorityLevel, std::priority_queue<
* std::shared_ptr<PriorityLevel>,
* std::vector<std::shared_ptr<PriorityLevel>>,
* ptr_less<std::shared_ptr<PriorityLevel>>>> prtyQ;
*
* }</pre>
*/
template<typename T, typename Cont = std::queue<std::shared_ptr<T>>>
class UtlThreadSafeQueue {
private:
mutable std::mutex mut;
Cont data_queue;
std::condition_variable data_cond;
std::size_t capacity;
std::atomic<bool> shutdownFlag;
public:
使用重载的自由函数助手。一种可能的方式:
template<class Q>
auto front_or_top(Q& q) -> decltype(q.front()) { return q.front(); }
template<class Q>
auto front_or_top(Q& q) -> decltype(q.top()) { return q.top(); }
然后front_or_top(cont)
。请注意,如果容器同时定义了 front()
和 top()
.
,则这是不明确的
或者,您也可以仅针对 queue
和 priority_queue
重载 front_or_top
:
template<class T, class Cont>
auto front_or_top(std::queue<T, Cont>& q) -> decltype(q.front()) { return q.front(); }
template<class T, class Cont, class Comp>
auto front_or_top(std::priority_queue<T, Cont, Comp>& q) -> decltype(q.top()) { return q.top(); }
我有一个通用的线程安全队列 class,它使用 std::priority_queue<std::shared_ptr<T>>
作为容器类型(通过模板参数指定)。但是,我想另外专门化它以使用更简单的 std::queue<std::shared_ptr<T>>
。不幸的是,这将意味着使用不同的技术来检索队列的最顶层元素(top()
代表 std::priority_queue<T>
或 front()
代表 std::queue<T>
)。我有一个 live coliru demo 显示了 priority_queue
类型的工作原型。但是,如果我尝试通过添加以下代码来使用 std::queue
:
我从编译器中得到预期的错误,指示 std::queue
没有 top()
方法。
我怀疑获得此权利的关键是对每个 wait_and_pop
方法使用 std::enable_if_t<T>
。我该怎么做?
编辑:感谢T.C的建议,我相信适用于 GCC 和 MSVC 的通用解决方案需要对 UtlThreadSafeQueue。有更新直播 coliru demo here:
// Note that overloading 2 function using expression SFINAE
// as shown here does not work on MSVC compiler - it does
// work on later builds of GCC though.
//template<class Q>
//auto front_or_top(Q& q) -> decltype(q.front()) {
// return q.front();
//}
//template<class Q>
//auto front_or_top(Q& q) -> decltype(q.top()) {
// return q.top();
//}
// this is a specific overload to work around the missing
// expression SFINAE in MSVC - for the std::queue<T>
template<class T>
auto front_or_top(std::queue<T>& q) -> decltype(q.front()) {
return q.front();
}
// this is a specific overload to work around the missing
// expression SFINAE in MSVC - for the std::priority_queue<T>
template<class T>
auto front_or_top(std::priority_queue<T>& q) -> decltype(q.top()) {
return q.top();
}
/**
* default type of container is a std::queue - which by default
* uses a std::deque<> of std::shared_ptr<T>'s. The default
* std::queue<T> does not need to order elements, and as
* such, it does not require an element comparator as is
* required by its priority queue counterpart.
*
* For the UtlThreadSafeQueue variant that uses a priority
* queue, we must define a comparator to compare
* <code>std::shared_ptr<T>'s</code>.
*
* To use a UtlThreadSafeQueue with a priority_queue container,
* use as follows:
*
* <pre>{@code
* // using priority queue
* UtlThreadSafeQueue<PriorityLevel, std::priority_queue<
* std::shared_ptr<PriorityLevel>,
* std::vector<std::shared_ptr<PriorityLevel>>,
* ptr_less<std::shared_ptr<PriorityLevel>>>> prtyQ;
*
* }</pre>
*/
template<typename T, typename Cont = std::queue<std::shared_ptr<T>>>
class UtlThreadSafeQueue {
private:
mutable std::mutex mut;
Cont data_queue;
std::condition_variable data_cond;
std::size_t capacity;
std::atomic<bool> shutdownFlag;
public:
使用重载的自由函数助手。一种可能的方式:
template<class Q>
auto front_or_top(Q& q) -> decltype(q.front()) { return q.front(); }
template<class Q>
auto front_or_top(Q& q) -> decltype(q.top()) { return q.top(); }
然后front_or_top(cont)
。请注意,如果容器同时定义了 front()
和 top()
.
或者,您也可以仅针对 queue
和 priority_queue
重载 front_or_top
:
template<class T, class Cont>
auto front_or_top(std::queue<T, Cont>& q) -> decltype(q.front()) { return q.front(); }
template<class T, class Cont, class Comp>
auto front_or_top(std::priority_queue<T, Cont, Comp>& q) -> decltype(q.top()) { return q.top(); }