I am curious if anyone knows why g++
compiles the code below but clang++
gives an error. The code creates a std::map<int, int, SortCriterion>
with a custom sort functor SortCriterion
. One can specify via the constructor of SortCriterion
the type of sorting: ascending or descending. The key comparison is implemented via operator()(int, int)
. Everything compiles and runs OK under g++
, even with -Wall, -Wextra, Wpedantic
etc. However, clang++
spits an error when invoking the insert
function, and complains about const
-ness for the comparison operator, i.e. wants operator()(int, int) const
.
note: candidate function not viable: 'this' argument has type
'const SortCriterion', but method is not marked const
bool operator()(int x, int y) //const
Now I know that keys in associative containers should not to be messed with, since will damage the internal structure of the container, but is const
-ness enforced by STL? It seems that the clang++
expects std::map<key, value, const comparator>
, whereas g++
does not impose const
.
PS: g++4.9
, Apple LLVM version 5.1 (clang-503.0.40)
#include <map>
#include <string>
#include <iostream>
using namespace std;
class SortCriterion
{
bool ascending;
public:
SortCriterion(bool sorting_type): ascending(sorting_type){};
// if operator below is not marked const,
// clang++ spits a compile-time error on insert
// however g++ compiles it ok
bool operator()(int x, int y) //const
{
if(ascending) // ascending
return x<y;
else
return x>y;
}
};
int main()
{
map<int, string, SortCriterion> m(SortCriterion(false)); // ascending
m.insert({1,"one element"}); // clang++ compile error here
m.insert({2,"another element"});
for(auto elem: m)
cout << elem.first << ": " << elem.second << endl;
}
The C++11 Standard documents a member of std::map
:
class value_compare {
friend class map;
protected:
Compare comp;
value_compare(Compare c) : comp(c) {}
public:
typedef bool result_type;
typedef value_type first_argument_type;
typedef value_type second_argument_type;
bool operator()(const value_type& x, const value_type& y) const {
return comp(x.first, y.first);
}
};
...given value_compare::operator()
is const
, it can't call a non-const
member on comp
. That means Compare
absolutely must have a const
operator()
for this part of the API to be usable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With