Ok, from your added information, the problem seems to be that addNode
takes a Node_ptr
per non-const
reference, while what the compiler has to call the function is a const boost::shared_ptr<Node>&
(note the const
). Let me explain:
std::set
is an associative container. Associative containers store their elements in some order, using the key element to define the ordering. If you would be allowed to change the key without the container knowing, you would invalidate the container's internal order. That's why I believe dereferencing a std::set<T>::iterator
does not return an modifiable lvalue. (Which means you cannot alter the reference returned. For example, if you have an iterator pos
into a std::set<int>
, *pos=42
should not compile.)
The catch with this is that only modifiable lvalues will bind to a non-const
reference. But what *pos
returns isn't a modifiable lvalue and thus won't. (So, in my example, int& r = *pos;
won't compile.) The reason is that, if this was allowed, you could change the sorting key through that non-const
reference behind the container's back and mess up the container's internal ordering.
That is why the result of your *pos
won't bind to a Node_ptr&
. And that in turn is why the compiler cannot call your function.
Does your addNode()
member function really alter the Node it's given? If not, it should take a const Node_ptr&
.
If it does, you have a design problem. You cannot alter an element that's in a set. The only thing you can do is to remove it from the set, change it, and add it back in.
On a side note: VC9 indeed compiles the following piece of code:
#include <iostream>
#include <set>
#include <typeinfo>
#include <iterator>
int main()
{
std::set<int> set;
set.insert(5);
std::cout << *set.begin() << '\n';
*set.begin() = 3; // this is an error!
std::cout << *set.begin() << '\n';
return (0);
}
I believe this is an error in VC9. Comeau rejects it.
Here's how to solve riddles with a compiler not calling a function you think it should call or calling the wrong function from a set of overloads.
The function you thought it should call is Graph::addNode(Node_ptr&)
. The code that you thought should call it is
addNode(*pos);
Change that code so that it provides the exact parameter(s) required:
Node_ptr& tmp = *pos;
addNode(tmp);
Now the call should definitely compile (or call the right overload), and the compiler should bark if it thinks *pos
cannot be assigned to to a Node_ptr&
.
Usually this tactic helps me to find out what's wrong in such situations.