【问题标题】:What are the differences with the following templated functions using default template parameters/arguments使用默认模板参数/参数的以下模板函数有什么区别
【发布时间】:2020-02-06 01:00:58
【问题描述】:

我想我不明白下面 5 个模板化函数之间有什么区别,希望有人能解释一下。什么时候应该使用每一个?

前 2 个没有默认模板参数,但后 2 个有。第一个和第三个将comp 的默认参数设置为default_comparer<data_t>(),但第二个和第四个没有。最后一个似乎没用,因为从不使用默认值。

template<typename data_t>
struct default_comparer {
  bool operator()(const data_t& d1, const data_t& d2) const 
  {
    return d1 < d2;
  }
};

第一个

template<typename data_t, typename comparer_t>
pair partition(std::vector<data_t>& list, size_t pivot_idx, size_t start, size_t end, 
    const comparer_t& comp = default_comparer<data_t>()) 
{
  //do stuff
}

第二个

template<typename data_t, typename comparer_t>
pair partition(std::vector<data_t>& list, size_t pivot_idx, size_t start, size_t end, 
    const comparer_t& comp = comparer_t()) 
{
  //do stuff
}

第三个

template<typename data_t, typename comparer_t = default_comparer<data_t>>
pair partition(std::vector<data_t>& list, size_t pivot_idx, size_t start, size_t end, 
    const comparer_t& comp = default_comparer<data_t>()) 
{
  //do stuff
}

第四个

template<typename data_t, typename comparer_t = default_comparer<data_t>>
pair partition(std::vector<data_t>& list, size_t pivot_idx, size_t start, size_t end, 
    const comparer_t& comp = comparer_t()) 
{
  //do stuff
}

第五个

template<typename data_t, typename comparer_t = default_comparer<data_t>>
pair partition(std::vector<data_t>& list, size_t pivot_idx, size_t start, size_t end, 
    const comparer_t& comp) 
{
  //do stuff
}

【问题讨论】:

    标签: c++ function templates default


    【解决方案1】:

    在大多数情况下,第四个版本是合理的版本。

    对于前两个版本,除非用户显式为comparer_t提供模板参数,否则不会使用默认参数,因为模板参数推导发生在插入默认参数之前;换句话说,在模板参数推导时不考虑默认参数。

    当用户显式提供comparer_t 模板参数时,第三版和第四版之间的区别就很明显了。在这种情况下,这些版本的默认参数不同——第三个版本需要从default_comparer&lt;data_t&gt; 转换,可能会导致错误。

    第五个版本与既没有给出默认模板参数也没有给出默认参数的假设版本之间的区别在于,前者允许将提供的默认模板参数用作回退,以防它的推导失败(例如,当用户提供{} 作为comp 的参数并且没有为comparer_t 提供模板参数时。

    顺便提一下,比较器这个词比比较器更常用。

    【讨论】:

    • 谢谢。在现代 C++ 中,您什么时候想要显式提供模板参数而不是自动推导出模板参数?
    • @Iamanon 在这种情况下不是,但在某些情况下您想手动传递参数。事实上,模板参数只是另一种形式的参数(连同函数参数)。例如:std::get&lt;2&gt;(tup),其中tupstd::tuple2 参数将确定返回类型,因此它必须作为编译时信息传递;在这种情况下,将其作为模板参数传递就足够了。
    • 啊有趣。在这种特殊情况下,为什么将元组的位置设计为模板参数而不是像std::get&lt;&gt;(tup,0) 这样的函数参数而不是std::get&lt;0&gt;(tup)
    • @Iamanon 问题是如果0 是一个普通的函数参数,它不能在编译时表达式中使用来确定返回类型。使用模板参数I,可以将返回类型指定为std::tuple_element_t&lt;Tuple, I&gt;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    相关资源
    最近更新 更多