--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: libstdc++6-4.7-dev: std::set<>::operator== uses operator== to compare elements
- From: Skuratovich Sergey Nikolaevich <ssn6@yandex.ru>
- Date: Wed, 19 Feb 2014 16:32:30 +0400
- Message-id: <20140219123230.9841.59818.reportbug@skur-pc.edc.local>
Package: libstdc++6-4.7-dev
Version: 4.7.2-5
Severity: important
Hello.
std::set<>::operator== uses operator== to compare elements instead of functor, specified in template parameters.
This makes imposible to compare sets of elements, which requires custom compare operator.
Minimal code example, which represents this wrong behaviour, is attached.
std::set<>::operator== uses underlying _Rb_tree container's operator== (stl_set.h:706),
which uses std::equal (stl_tree.h:867) to compare content by specifying iterators range.
std::equal, in turn, uses operator== to compare elements (stl_algobase.h:791).
-- System Information:
Debian Release: 7.4
APT prefers stable
APT policy: (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 3.2.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=ru_RU.UTF-8, LC_CTYPE=ru_RU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages libstdc++6-4.7-dev depends on:
ii g++-4.7 4.7.2-5
ii gcc-4.7-base 4.7.2-5
ii libc6-dev 2.13-38+deb7u1
ii libstdc++6 4.7.2-5
libstdc++6-4.7-dev recommends no packages.
Versions of packages libstdc++6-4.7-dev suggests:
pn libstdc++6-4.7-doc <none>
-- no debconf information
#include <set>
#include <iostream>
#include <memory>
template <
class C,
class PtrType = std::shared_ptr<C>,
class Compare = std::less<C>
>
class CompareByValue {
public:
CompareByValue(): cmp() {}
inline bool operator()(const PtrType& _1, const PtrType& _2) const {
return _1 ? (_2 && cmp(*_1, *_2)) : bool(_2);
}
private:
Compare cmp;
};
// Simple class with operator<.
class A {
public:
A(const std::size_t i_): i(i_) {}
bool operator<(const A& other) const {return i < other.i;}
std::size_t getI() const {return i;}
private:
const std::size_t i;
};
std::ostream& operator<<(std::ostream& stream, const A& c) {
return stream << c.getI();
}
int main(int, char**) {
typedef std::set<std::shared_ptr<A>, CompareByValue<A> > Set;
using std::make_shared;
// Initializing containers
Set s0{make_shared<A>(1), make_shared<A>(2), make_shared<A>(3)};
Set s1{make_shared<A>(1), make_shared<A>(2), make_shared<A>(3)};
// Print containers content
for (const auto& s : {s0, s1}) {
for (const auto i : s)
std::cout << *i << " ";
std::cout << std::endl;
}
// Manually compare elements using CompareByValue<> and print results.
CompareByValue<A> cmp;
for (auto i0 = s0.begin(), i1 = s1.begin(); i0 != s0.end(); ++i0, ++i1) {
std::cout << (!(cmp(*i0, *i1) || cmp(*i0, *i1))) << " ";
}
std::cout << std::endl;
// Comparing containers using std::set<>::operator== ...Oops!
std::cout << std::boolalpha << (s0 == s1) << std::endl;
}
--- End Message ---