Reputation: 3224
This question is best asked by example. Say I want to declare a std::priority_queue
with a comparator function. I could do:
auto cmp_fn = [](const std::string& left, const std::string& right) {
return right < left;
};
std::priority_queue<std::string, std::vector<std::string>, decltype(cmp_fn)> queue(cmp_fn);
Is there any way to avoid specifying the middle template parameter so that the default is used? Something like
auto cmp_fn = [](const std::string& left, const std::string& right) {
return right < left;
};
std::priority_queue<std::string, /* use default */, decltype(cmp_fn)> queue(cmp_fn);
Note: This is a simplified example of something more complicated I'm doing. Please don't answer with suggestion of the form: "just use std::greater
". My question is about the template arguments.
Upvotes: 2
Views: 199
Reputation: 66200
If you're interested in a specific solution for the second template parameter of std::priority_queue
, I suppose you can use the typename std::priority_queue<T>::container_type
in some way (see, by example, the solution from nwp; +1).
If your interested in a more general solution (non only for the second default template type, non only for std::priority_queue
), I suppose you can first develop a type trait type_n
to estract the n-th type from a list
template <std::size_t N, typename T0, typename ... Ts>
struct type_n
{ using type = typename type_n<N-1U, Ts...>::type; };
template <typename T0, typename ... Ts>
struct type_n<0U, T0, Ts...>
{ using type = T0; };
next a type traits type_cnt_n
(that use type_n
) to extract the n-th type argument of a template-template parameter
template <std::size_t, typename>
struct type_cnt_n;
template <std::size_t N, template <typename ...> class Cnt, typename ... Ts>
struct type_cnt_n<N, Cnt<Ts...>>
{ using type = typename type_n<N, Ts...>::type; };
and last (following the answer from nwp) a make_priority_queue()
function
template <typename T, typename Cmp>
auto make_priority_queue (Cmp const & cmp)
{ return std::priority_queue<T,
typename type_cnt_n<1U, std::priority_queue<T>>::type, Cmp> { cmp }; }
The problem of this solution is that works only with template-template types with type-only template parameter (so works with std::priority_queue
, with std::vector
, with std::map
but doesn't work with std::array
).
The following is a full working ... well, a full compiling... example
#include <queue>
#include <iostream>
template <std::size_t N, typename T0, typename ... Ts>
struct type_n
{ using type = typename type_n<N-1U, Ts...>::type; };
template <typename T0, typename ... Ts>
struct type_n<0U, T0, Ts...>
{ using type = T0; };
template <std::size_t, typename>
struct type_cnt_n;
template <std::size_t N, template <typename ...> class Cnt, typename ... Ts>
struct type_cnt_n<N, Cnt<Ts...>>
{ using type = typename type_n<N, Ts...>::type; };
template <typename T, typename Cmp>
auto make_priority_queue (Cmp const & cmp)
{ return std::priority_queue<T,
typename type_cnt_n<1U, std::priority_queue<T>>::type, Cmp> { cmp }; }
int main()
{
auto cmpFn = [](std::string const & l, std::string const &r)
{ return r < l; };
auto pq = make_priority_queue<std::string>(cmpFn);
}
Upvotes: 1
Reputation: 9991
You can use this:
template <class T, class Comparator>
using dcpq = /*default container priority queue*/
std::priority_queue<T, typename std::priority_queue<T>::container_type, Comparator>;
to be used like
int main() {
auto cmp_fn = [](const std::string &left, const std::string &right)
{ return right < left; };
dcpq<std::string, decltype(cmp_fn)> queue(cmp_fn);
}
although directly writing
std::priority_queue<std::string, typename std::priority_queue<T>::container,
decltype(cmp_fn)> queue(cmp_fn);
might be easier.
Upvotes: 3