Reputation: 2241
Consider a std::map<const char *, MyClass*>
.
How do I access a member (variable or function) of the MyClass
object pointed to by the map?
// assume MyClass has a string var 'fred' and a method 'ethel'
std::map<const char*, MyClass*> MyMap;
MyMap[ "A" ] = new MyClass;
MyMap.find( "A" )->fred = "I'm a Mertz"; // <--- fails on compile
MyMap.find( "A" )->second->fred = "I'm a Mertz"; // <--- also fails
EDIT -- per Xeo's suggestion
I posted dummy code. Here is the real code.
// VarInfo is meta-data describing various variables, type, case, etc.
std::map<std::string,VarInfo*> g_VarMap; // this is a global
int main( void )
{
// ........ g_VarMap["systemName"] = new VarInfo;
g_VarMap.find( "systemName" ).second->setCase( VarInfo::MIXED, VarInfo::IGNORE );
// .....
}
errors were:
struct std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, VarInfo*> >’ has no member named ‘second’
Field 'second' could not be resolved Semantic Error make: *** [src/ACT_iod.o] Error 1 C/C++ Problem
Method 'setCase' could not be resolved Semantic Error –
Upvotes: 2
Views: 6683
Reputation: 7908
The problem is that an iterator is a pointer type, not a reference type, so iter.second
will fail to compile.
Instead, you must use the pointer syntax: iter->second
(arrow instead of dot).
Consider this short example:
#include <iostream>
#include <map>
int main()
{
std::map<int, std::string> myMap;
std::map<int, std::string>::iterator it;
std::map<int, std::string>::iterator end = myMap.end();
myMap.insert(std::pair<int, std::string>(0, "hello"));
myMap.insert(std::pair<int, std::string>(1, "world"));
for(it = myMap.begin(); it != end; ++it)
{
// std::cout << "Value: " << it.second << "\n";
// The previous line will fail to compile with error:
// ‘struct std::_Rb_tree_iterator<std::pair<const int,
// std::basic_string<char, std::char_traits<char>,
// std::allocator<char> > > >’ has no member named ‘second’
// The following line is correct
std::cout << "Value: " << it->second << "\n";
}
}
Upvotes: 1
Reputation: 9063
It fails because std::map<T, Y>::find()
returns an iterator, not a reference to an MyMap object. The correct code would be:
map<const char*, MyClass*>::iterator a;
a = MyMap.find("A");
// a->fred; this is wrong too
a->second->fred = "Whatever";
Upvotes: 2
Reputation: 19032
std::map
stores types internally as a std::pair
, and std::map::find
, returns an iterator
. So, to access members of your class, you have to go through the iterator
, which presents the key_type
as first
, and the value_type
as second
. Also, as others have stated, you should probably not be using const char*
as your key_type
. Here's a short example.
#include <string>
#include <map>
#include <iostream>
struct T
{
T(int x, int y) : x_(x), y_(y)
{}
int x_, y_;
};
int main()
{
typedef std::map<std::string, T> map_type;
map_type m;
m.insert(std::make_pair("0:0", T(0,0)));
m.insert(std::make_pair("0:1", T(0,1)));
m.insert(std::make_pair("1:1", T(1,1)));
// find the desired item (returns an iterator to the item
// or end() if the item doesn't exist.
map_type::const_iterator t_0_1 = m.find("0:1");
if(m.end() != t_0_1)
{
// access via the iterator (a std::pair) with
// key stored in first, and your contained type
// stored in second.
std::cout << t_0_1->second.x_ << ':' << t_0_1->second.y_ << '\n';
}
return 0;
}
Upvotes: 8
Reputation: 153929
The most obvious method is
MyMap[key]->fred
, but
MyMap.find( key )->second->fred
should also work. In both cases, you must ensure that the key is present before using it. In the code you've written, it (usually) won't be, since you're using the address of a specific instance of a string literal as key; a compiler is allowed to merge instances with the same value, but is not required to.
Upvotes: 1