Reputation: 14839
Assume I have class MyClass
class MyClass
{
public:
MyClass( std::string str ) : _str(str) {}
void SetPosition ( int i ) { _pos = i; }
std::string _str;
int _pos;
};
namespace std
{
template<> struct hash<shared_ptr<MyClass>>
{
size_t operator()( const shared_ptr<MyClass> & ptr ) const
{
return hash<string>()( ptr->_str ) + hash<int>()( ptr->_pos );
}
};
}
When using std::vector, I was able to do this:
std::string str = "blah";
auto ptr = std::make_shared<MyClass>( str );
std::vector<std::shared_ptr<MyClass>> vector;
vector.push_back( ptr );
ptr->SetPosition ( std::addressof( vector.back() ) - std::addressof( vector[0] ) );
std::cout << ptr->_str << " is at " << ptr->_pos << std::endl;
In order to calculate where in the vector, my object pointer was placed.
However, If I want to use std::unordered_set (which I do), then:
std::string str = "blah";
auto ptr = std::make_shared<MyClass>( str );
std::unordered_set<std::shared_ptr<MyClass>> set;
auto res = set.insert( ptr );
ptr->SetPosition ( std::addressof( res.first ) - std::addressof( set[0] ) );
std::cout << ptr->_str << " is at " << ptr->_pos << std::endl;
Will not work. Neither will
std::addressof( set.begin() );
Nor will,
std::addressof( set.begin().first );
or any other way I try to use the front iterator.
Upvotes: 0
Views: 1717
Reputation: 303147
unordered_set, like the name implies, is unordered. You can keep track of the position of your elements in a vector, because as long as you don't erase anything, they won't change places. But that's not true of unordered_set. For instance, on my implementation, here's what printing all the elements in order after every insert would yield:
std::unordered_set<int> s;
s.insert(0); // 0
s.insert(1); // 1 0
s.insert(2); // 2 1 0
s.insert(3); // 3 2 1 0
...
s.insert(22); // 22 0 1 2 3 ... 19 20 21
...
s.insert(48); // 48 47 46 45 ... 22 0 1 2 3 4 ... 21
So what I'm trying to say is order is definitely not something that makes sense for you to rely on.
With your vector, however, you can do much better in terms of setting position:
vector.push_back(ptr);
ptr->SetPosition(vector.size() - 1);
Upvotes: 3