MohsenTamiz MohsenTamiz - 1 month ago 9
C++ Question

Searching const key type in set causes compile error

I have a

set
of a pointer type but searching using a const pointer is impossible, my code is such as below:

#include <set>
#include <string>

using namespace std;

struct Node
{
string name;
int id;

Node(const string &name, int id):
name(name),
id(id)
{}
};

struct Comprator
{
bool operator()(const Node* lhs, const Node* rhs) const
{
return lhs->id < rhs->id;
}
};

int
main(int argc, char *argv[])
{
set<Node*, Comprator> d;

Node* node3 = new Node("foo", 4);

d.insert(node3);

const Node* node4 = node3;

auto it = d.find(node4);

return 0;
}


I get the following error:

main.cc: In function ‘int main(int, char**)’:
main.cc:38:25: error: invalid conversion from ‘const Node*’ to ‘std::set<Node*, Comprator>::key_type {aka Node*}’ [-fpermissive]
auto it = d.find(node4);
^
In file included from /usr/include/c++/5/set:61:0,
from main.cc:2:
/usr/include/c++/5/bits/stl_set.h:694:7: note: initializing argument 1 of ‘std::set<_Key, _Compare, _Alloc>::iterator std::set<_Key, _Compare, _Alloc>::find(const key_type&) [with _Key = Node*; _Compare = Comprator; _Alloc = std::allocator<Node*>; std::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<Node*>; std::set<_Key, _Compare, _Alloc>::key_type = Node*]’
find(const key_type& __x)


If I change
Node*
to
int
every thing works, I do not understand the problem. I use c++11 and g++-5.4.0.

Edit:

As @Piotr Skotnicki explained in the comments in c++14 the below code for comparator could compile:

struct Comprator
{
using is_transparent = void;

bool operator()(const Node* lhs, const Node* rhs) const
{
return lhs->id < rhs->id;
}
};

Answer

const Node* (a non-const pointer to const Node) is not const key - that would be Node* const (a const pointer to Node).

Either change your set to be a set of Node const*, or pass pointer to non-const Nodes to it.

Here's a more in-depth explanation: link