以下使用默认模板 parameters/arguments 的模板化函数有什么区别

What are the differences with the following templated functions using default template parameters/arguments

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

前两个没有默认模板参数,但后两个有。第一个和第三个将 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
}

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

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

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

第五版与既不给出默认模板参数也不给出默认参数的假设版本的区别在于,前者允许提供的默认模板参数用作后备,以防推导失败(对于例如,当用户提供 {} 作为 comp 的参数并且没有为 comparer_t).

提供模板参数时

顺便说一句,请注意术语 comparatorcomparer 更常用。