使用默认模板参数

Using default template argument

这个问题最好通过例子来问。假设我想声明一个带有比较函数的 std::priority_queue 。我能做到:

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);

有什么方法可以避免指定中间的模板参数而使用默认值吗?像

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);

注意:这是我正在做的更复杂的事情的简化示例。请不要回答以下形式的建议:"just use std::greater"。我的问题是关于模板参数。

你可以使用这个:

template <class T, class Comparator>
using dcpq = /*default container priority queue*/
    std::priority_queue<T, typename std::priority_queue<T>::container_type, Comparator>;

一样使用
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);
}

虽然直接写

std::priority_queue<std::string, typename std::priority_queue<T>::container,
    decltype(cmp_fn)> queue(cmp_fn);

可能会更容易。

如果您对 std::priority_queue 的第二个模板参数的特定解决方案感兴趣,我想您可以以某种方式使用 typename std::priority_queue<T>::container_type(例如,参见 nwp 的解决方案; +1).

如果您对更通用的解决方案感兴趣(不仅针对第二个默认模板类型,也不仅仅针对 std::priority_queue),我想您可以先开发一个类型特征 type_n 来提取列表中的第 n 个类型

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; };

下一个类型特征 type_cnt_n(使用 type_n)提取模板模板参数的第 n 个类型参数

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; };

最后(根据 nwp 的回答)一个 make_priority_queue() 函数

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 }; }

这个解决方案的问题是它只适用于带有类型模板参数的模板模板类型(因此适用于 std::priority_queuestd::vectorstd::map 但不'使用 std::array).

以下是一个完整的工作...嗯,一个完整的编译...示例

#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);
 }