Inspired by SFINAE to check if std::less will work, I come to this:
template <typename F, typename S, typename = void>
struct QueueImpl {
using type = std::queue<std::pair<F, S>>;
};
template <typename F, typename S>
struct QueueImpl<F, S, decltype(std::declval<F>() < std::declval<F>())> {
using type = std::priority_queue<std::pair<F, S>>;
};
template <typename F, typename S>
using Queue = typename QueueImpl<F, S>::type;
with the intention that if <
has been defined for type F
, Queue
will be std::priority_queue
and otherwise std::queue
. But it seems always to match the std::queue
case:
class C {};
int main()
{
Queue<int, char> q1;
Queue<C, char> q2;
std::cout << typeid(q1).name() << std::endl;
std::cout << typeid(q2).name() << std::endl;
return 0;
}
which shows both Queue
's are std::queue
:
St5queueISt4pairIicESt5dequeIS1_SaIS1_EEE
St5queueISt4pairI1CcESt5dequeIS2_SaIS2_EEE
My second attempt uses std::conditional
:
template <typename F, typename S>
using Queue = typename std::conditional_t<
std::is_same_v<bool, decltype(std::declval<F>() < std::declval<F>())>,
std::priority_queue<std::pair<F, S>>,
std::queue<std::pair<F, S>>>;
For q1
, it successfully chooses std::priority_queue
and prints St14priority_queueISt4pairIicESt6vectorIS1_SaIS1_EESt4lessIS1_EE
. But when q2
is defined in the same way as the first attempt, the code cannot compile:
error: no match for ‘operator<’ (operand types are ‘C’ and ‘C’)
So how to make the code work?