C++ 如何正确地将比较器传递给另一个模板函数

C++ 如何正确地将比较器传递给另一个模板函数,c++,templates,C++,Templates,我需要一个函数,它将使用两个迭代器和一个自定义比较器来比较这个迭代器的值。我不想为此使用其他模板参数。我以这种方式实现了它: template<typename T> void foo(T begin, T end, function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>()) { // I want to use 'compare' a

我需要一个函数,它将使用两个迭代器和一个自定义比较器来比较这个迭代器的值。我不想为此使用其他模板参数。我以这种方式实现了它:

template<typename T>
void foo(T begin, T end,
  function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>())
{
    // I want to use 'compare' as: "compare(*begin, *begin);"
}
模板
无效foo(T开始,T结束,
函数compare=less())
{
//我想将“compare”用作:“compare(*begin,*begin);”
}
这段代码通常是通过clang编译的,但在GCC 5.4.0上我有一些错误:

binary_heap.cpp:10:79: error: local variable 'begin' may not appear in this context
   function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>())
                                                                               ^
binary_heap.cpp:10:85: error: template argument 1 is invalid
   function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>())
binary\u heap.cpp:10:79:错误:局部变量“begin”可能不在此上下文中出现
函数compare=less())
^
二进制堆.cpp:10:85:错误:模板参数1无效
函数compare=less())

如何更正此代码,以便在clang和GCC上成功编译?或者,有没有更合适的方法来定义这样的函数?

您不能在默认参数中使用参数,即使在未赋值的上下文中也是如此(尽管可能应该修改标准以放宽该限制)。不要使用
decltype(*begin)
,而是使用

decltype(*std::declval<T&>())

编辑2:我同意krzaq的观点,最好只添加另一个模板参数。

仅通过强制使用
函数(更多详细信息),您就对算法的性能感到非常悲观。只要拿一个
Compare
,你就是黄金:

template<typename T, typename Compare = std::less<typename iterator_traits<T>::value_type>>
void foo(T begin, T end, Compare compare = {})
{
    // I want to use 'compare' as: "compare(*begin, *begin);"
}

添加另一个模板参数
Compare
。这使得编译器更容易进行内联。当我在这里的时候,支援哨兵

template<class It, class Sentinel, class Compare=std::less<void>>
void foo(It begin, Sentinel end, Compare cmp={}) {
}
模板
void foo(它开始,哨兵结束,比较cmp={}){
}
但是,假设C++14,除上述情况外,我会这样做:

template<class T>
using comparator_sig = bool(T const&,T const&);
template<class T>
using comparator = std::function<comparator_sig<T>>;
template<class It>
using compare_inside_it = comparator<
  typename std::iterator_traits<It>::value_type
>;

template<typename T>
void foo(T begin, T end, compare_inside_it<T> compare = less<>) {
}
模板
使用比较器_sig=bool(T常数&,T常数&);
模板
使用comparator=std::function;
模板
在比较器中使用compare\u<
typename std::迭代器特征::值类型
>;
模板
void foo(T begin,T end,compare_inside_it compare=less){
}
在C++11中,我会编写自己的
less

struct compare\u less{
模板
布尔运算符(){
返回std::less{}(lhs,rhs);
}
};
并且做:

template<typename T>
void foo(T begin, T end, compare_inside_it<T> compare = compare_less{}) {
}
模板
void foo(T begin,T end,compare_in_it compare=compare_less{}){
}
甚至只是做:

template<typename T>
void foo(T begin, T end, compare_inside_it<T> compare = {}) {
  if (!compare) compare=compare_less{};
}
模板
void foo(T begin,T end,compare_in_it compare={}){
如果(!compare)compare=compare_less{};
}

为什么不想为此使用额外的模板参数?出于好奇,您使用
函数在哪些方面对性能感到悲观?@krzaq谢谢!如果我对最佳性能感兴趣,我应该选择哪种解决方案?@0x1337我会在不受太多干扰的情况下传递模板参数。它会产生稍差的错误消息(希望能用概念来修复),但可读性好,速度快,与标准库一致。看看
Compare
是怎么做的,我会用
{}
而不是
Compare{}
跟着DRY。
struct compare_less {
  template<class T>
  bool operator()( T const& lhs, T const& rhs ) const {
    return std::less<T>{}(lhs, rhs);
  }
};
template<typename T>
void foo(T begin, T end, compare_inside_it<T> compare = compare_less{}) {
}
template<typename T>
void foo(T begin, T end, compare_inside_it<T> compare = {}) {
  if (!compare) compare=compare_less{};
}