【问题标题】:Using default template argument使用默认模板参数
【发布时间】:2017-09-16 07:40:45
【问题描述】:

这个问题最好通过例子来问。假设我想声明一个带有比较器函数的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);

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

【问题讨论】:

  • 不是直接的,但是模板别名肯定是可行的,不是吗?

标签: c++ c++11 templates variadic-templates template-templates


【解决方案1】:

你可以用这个:

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&lt;T&gt;::container_type 代替decltype(get_queue_storage(std::priority_queue&lt;T&gt;{})) 怎么样?我想你可以不用get_queue_storage()
  • @max66 是的,那样会更聪明。
【解决方案2】:

如果您对std::priority_queue 的第二个模板参数的特定解决方案感兴趣,我想您可以以某种方式使用typename std::priority_queue&lt;T&gt;::container_type(例如,请参阅来自 nwp 的解决方案;+1)。

如果您对更通用的解决方案感兴趣(不仅适用于第二个默认模板类型,也不仅仅适用于 std::priority_queue),我想您可以先开发一个类型特征 type_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);
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    相关资源
    最近更新 更多