为什么我不能重载我传递给std :: upper_bound的比较器

时间:2017-02-14 07:54:32

标签: c++ c++11 stl

我是C ++的新手,并且认为重载函数总是好的,通过重载我的意思是:

  

C ++中的函数重载您可以在同一范围内对同一函数名称有多个定义。函数的定义必须通过参数列表中的参数的类型和/或数量彼此不同。您不能重载仅因返回类型而不同的函数声明。

然而,当我编写下面的代码时,它没有编译,我的印象是std :: upper_bound无法解析它应该使用哪个比较器,尽管它看起来很容易,因为只有一个具有正确的签名。< / p>

编辑这些函数位于命名空间中的实用程序文件(不是类)中。

我是在this post

后执行此操作的

我在这里可能完全错了,你能解释一下吗

  1. 为什么代码无法编译
  2. 我如何能够编写2个具有代码编译和runnable
  3. 的不同签名的实现
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <algorithm>
    
    //I have a utility file where functions are defined in a namespace
    namespace util{
      bool lt(double y, const std::pair<double, long>& x) { 
          return x.first < y;
      }
      //If this function is commented the whole will compile and run
      bool lt(const std::pair<double, long>& x, double y) {
          return x.first < y;
      }
    }
    
    int main()
    {
      std::vector<std::pair<double,long> > v;
      v.push_back(std::make_pair(999., 123));
      v.push_back(std::make_pair(100., 3));
      v.push_back(std::make_pair(15., 13));
      v.push_back(std::make_pair(10., 12));
      v.push_back(std::make_pair(1., 2));
      //use upper_bound
      std::vector<std::pair<double,long> >::iterator it =
          std::upper_bound(v.begin(), v.end(), 25., util::lt);
      std::cout << " it->first => " << it->first << std::endl;
    }
    

2 个答案:

答案 0 :(得分:3)

您拨打upper_bound的地方不是lt的呼叫网站,因此此处没有重载解决方案,并且您的重载不明确。

#include <algorithm>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>

bool lt(const std::pair<double, long>& x, const std::pair<double, long>& y)
{
    return x.first < y.first;
}

int main()
{
    std::vector<std::pair<double, long>> v;
    v.push_back(std::make_pair(999., 123));
    v.push_back(std::make_pair(100., 3));
    v.push_back(std::make_pair(15., 13));
    v.push_back(std::make_pair(10., 12));
    v.push_back(std::make_pair(1., 2));
    // use upper_bound
    std::vector<std::pair<double, long>>::iterator it =
        std::upper_bound(v.begin(), v.end(), std::make_pair(25., 0.), lt);
    std::cout << " it->first => " << it->first << std::endl;
}

答案 1 :(得分:2)

因为function serialize(obj, prefix) { var str = [], p; for (p in obj) { if (obj.hasOwnProperty(p)) { var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p]; str.push((v !== null && typeof v === "object") ? serialize(v, k) : encodeURIComponent(k) + "=" + encodeURIComponent(v)); } } return str.join("&"); } var data = serialize({ valueA: input.value }); xhrRequest(data, "POST", "post.php" ... 模板的谓词类型(您传递的函数),所以要使用的特定重载必须在之前知道查看std::upper_bound的任何主体(这是可以执行重载决策的地方,因为参数是已知的)。围绕这个有各种各样的方法,它们都不是特别漂亮:

  • 投射到确切类型:

    upper_bound
  • 将呼叫包裹在lambda中:

    std::upper_bound(v.begin, v.end(), 25.0, static_cast<bool (*)(double, const std::pair<double, long>&>(lt))
    
  • 将函数放在类中,以便使用类的类型实例化模板,然后在模板体内发生重载解析:

    [](auto x, auto y){ return lt(x, y); }
    

请注意,后两个选项几乎相同的东西!

事实上,我建议你停下来想想你在做什么。在两种完全不同的类型之间提供订购真的有意义吗?你的第一个函数实际上似乎是实现struct LT { bool operator()(double y, const std::pair<double, long>& x) { return x.first < y; } bool operator()(const std::pair<double, long>& x, double y) { return x.first < y; } }; // ... std::upper_bound(v.begin(), v.end(), 25.0, LT()); (大于),也许它应该是gt

我也真的考虑使用endl做一个不好的做法(我知道不是每个人都同意我的意见)。