Вы можете использовать constexpr, если , и проверить, если T
равно std::move_constructible_v
.
Я бы также создал emplace
прокси:
#include <type_traits>
template<typename T>
class Queue {
std::queue<T> q;
public:
decltype(auto) pop() {
if constexpr(std::is_move_constructible_v<T>) {
T t = std::move(q.front());
q.pop();
return t;
} else {
T t = q.front();
q.pop();
return t;
}
}
template<class... Args>
decltype(auto) emplace(Args&&... args) {
return q.emplace(std::forward<Args>(args)...);
}
};
Вот версия C ++ 11 (раньше я не замечал тег C ++ 11). Удаление конструктора перемещения и оператора присваивания перемещения в CopyOnly
действительно приводило к путанице. Вы, вероятно, никогда не должны делать это в реальном коде.
Чтобы заставить CopyOnly co = qc.pop();
работать, pop()
должен возвращать const T
, иначе конструктор перемещения будет частью разрешения перегрузки, которое все равно будет даже если он удален, но компиляция не удастся только потому, что он удален.
Если для вас подходит CopyOnly&& co = qc.pop();
, вы можете заменить const U
на U
в enable_if
.
template<typename T>
class Queue {
std::queue<T> q{};
public:
template<typename U = T>
typename std::enable_if<std::is_move_constructible<U>::value, U>::type
pop() {
U t = std::move(q.front());
q.pop();
return t;
}
template<typename U = T>
typename std::enable_if<!std::is_move_constructible<U>::value, const U>::type
pop() {
U t = q.front();
q.pop();
return t;
}
template<class... Args>
void emplace(Args&&... args) {
q.emplace(std::forward<Args>(args)...);
}
};
Вот еще одна версия C ++ 11, построенная на идее rafix07, с дополнительным типом popper
, который делает pop
после возврата, чтобы устранить возможную ошибку в g cc 7.3.
template<typename T>
class Queue {
std::queue<T> q{};
struct popper {
std::queue<T>& q_ref;
~popper() {
q_ref.pop();
}
};
public:
using Type = typename
std::conditional<std::is_move_constructible<T>::value, T, T&>::type;
T pop() {
popper pop_after_return{q};
return std::forward<Type>(q.front());
}
template<class... Args>
void emplace(Args&&... args) {
q.emplace(std::forward<Args>(args)...);
}
};