【问题标题】:C++ creating sorted vector from mapC ++从地图创建排序向量
【发布时间】:2014-07-27 03:42:06
【问题描述】:

我正在尝试从map 创建一个排序的vector,根据不是地图键的值进行排序。 映射值为block对象,我希望向量按照sizeblock的属性进行排序。
我的代码:

#include <map>
#include <string>
#include <vector>

struct block {
    string data;
    int size;
};

struct vecotrCompare {
    bool operator()(pair<const string, block*> &left,
      pair<const string, block*> &right) {
        return left.second -> size < right.second -> size;
    }
};

int main() {
    map<const string, block*> myMap;
    vector<pair<const string, block*> > myVector(
      myMap.begin(), myMap.end());
    sort(myVector.begin(), myVector.end(), vecotrCompare());
}

sort(...) 行无法编译,并且出现编译错误:

error: no match for call to ‘(vecotrCompare) (std::pair<const
  std::basic_string<char>, block*>&, const std::pair<const
  std::basic_string<char>, block*>&)’

【问题讨论】:

  • required from here 只是错误的一部分,也是最没用的部分。
  • 总是发布完整的错误
  • 无论如何,向量中不能有不可复制的对象(比如一对const 的东西)。它在地图中是多余的,除此之外将无法使用。
  • 我更新了问题,谢谢
  • 干得好!通过从vecotrCompare::operator() 的参数中删除const&amp;,您已经完全改变了错误以及您看到它的原因。重新添加const&amp;,您将遇到下一个错误,我在回答中已对此进行了解释。

标签: c++ sorting vector map


【解决方案1】:

vector 中的元素需要是 MoveAssignable 或 CopyAssignable。 pair&lt;const string, block*&gt; 既不是由于const string。将其更改为 string 并编译您的代码。

map<string, block*> myMap;
vector<pair<string, block*> > myVector(myMap.begin(), myMap.end());

同时更改比较器,使参数类型为const&amp;

struct vecotrCompare {
    bool operator()(pair< string, block*> const&left, 
                    pair< string, block*> const&right) const {
        return left.second -> size < right.second -> size;
    }
};

Live demo


关于需要const&amp; 的参数的第二部分实际上不是必需的。来自 §25.1/9

当算法需要一个函数对象时使用BinaryPredicate参数,当T是签名的一部分时,该函数对象应用于解引用两个相应迭代器的结果或解引用迭代器并键入T返回一个值可测试为true。换句话说,如果一个算法将BinaryPredicate binary_pred 作为它的参数,并将first1first2 作为它的迭代器参数,它应该在binary_pred(*first1, *first2) 上下文转换为bool 的构造中正确工作(第4 条)。 BinaryPredicate 总是将第一个迭代器的 value_type 作为它的第一个参数,也就是说,当 T 值是签名的一部分时,它应该在构造 binary_pred(*first1, value) 上下文转换为 bool 时正常工作(第 4 条)。 binary_pred 不应通过取消引用的迭代器应用任何非常量函数

所以标准从来没有提到函子的参数类型必须是 const&amp;,但 libstdc++ 似乎将临时变量传递给函子和代码doesn't compile,除非你添加const&amp;(看起来这已在 gcc-4.9 中修复)。

另一方面,libc++ 和 VS2013 handle the case 的参数都不是正确的 const&amp;

【讨论】:

  • 几乎; OP 从函子的参数类型中删除了 const,没有明显的原因。他需要重新添加它。
  • @LightnessRacesinOrbit 没什么好奇怪的!我知道第一次尝试时编译的代码。只需再次复制粘贴他的代码并重试以确保我在弄乱它时没有任何调整,当然,它不会再编译了!
【解决方案2】:

除了@Praetorian 建议的更改之外,您应该在vectorCompare::operator() 中添加一些const

struct vecotrCompare {
    bool operator()(pair<const string, block*> const& left,
                    pair<const string, block*> const& right) const {
        return left.second -> size < right.second -> size;
    }
};

这是关于comp 要求的文档,来自 http://www.cplusplus.com/reference/algorithm/sort/.

比较

二进制函数,接受范围内的两个元素作为参数,并返回一个可转换为 bool 的值。返回的值指示作为第一个参数传递的元素是否被认为在其定义的特定严格弱排序中位于第二个之前。

该函数不得修改其任何参数。

这可以是函数指针或函数对象。

一些编译器强制参数类型为const&amp; 或按值传递的对象。其他人使用参考。

【讨论】:

  • 解释为什么,而不是仅仅转储代码。这是因为sort 为比较器提供了一些临时值(右值),而这些不会绑定到非const ref。
  • @LightnessRacesinOrbit 很好的建议。我更新了答案。
  • The function shall not modify any of its arguments implies that types of the argument [etc] 不,它没有。这不是原因。
  • @LightnessRacesinOrbit 在这种情况下,我错过了这方面的一些重要方面。
  • @Praetorian:不,我的意思是,不修改参数的要求与要求参数为const 类型的要求相同。也就是说,引用的规则不相关。您可以在替代标准库实现中使用非const 参数进行排序,这只会进一步巩固我的说法,即这个答案并不完全正确。正如我所说,问题的原因是 libstdc++ 正在传入临时文件。你自己的回答在这一切上都同意我的看法。
猜你喜欢
  • 2010-10-13
  • 2011-06-24
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多