Reputation: 544
I have an Item
class that can carry multiple types of data, including a std::map<Item, Item>
.
I have defined operator[]
to do the following: if Item is not of type V_MAP (V_MAP is part of an enum where I specify the type carried), Item changes its type to V_MAP. After this "cast", it returns internalMap [ ItemPassedAsArgument ]
. The operator has the following declaration:
Item& operator[] (const Item& itemArg);
It works fine, I have tested in various ways.
Now, this needs to be integrated with some other stuff, first of that stuff being ClassX.
ClassX has a member of type Item(V_MAP). It needs to hold stuff. It (ClassX) also has a member method defined as follows:
std::string ClassX::getSmth () const {
return item[keySmth];
}
where keySmth is
const std::string ClassX::keySmth ("blablabla");
I AM NOT ALLOWED TO CHANGE THE DEFINITION OF THE getSmth()
METHOD. That const needs to stay there, that method should only inspect things.
As you can see, the method can not change anything, so it contradicts with my operator. When used like this, the error said No operator[] matches these operands.Operands are const Item [ const std::string ]
.
Therefore, I have overloaded the operator[]
to do almost the same thing, except the part where it changes the type of the Item
, and return a const Item
. This is it's declaration:
const Item& operator[] (const Item& itemArg) const;
It is now up to the programmer to ensure that the subscript operator is now applied only on Item
s of type V_MAP.
But now I get the following compiler error:
error C2668: 'std::basic_string<_Elem,_Traits,_Alloc>::basic_string' : ambiguous call to overloaded function
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Alloc=std::allocator<char>
]
c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstring(896): could be 'std::basic_string<_Elem,_Traits,_Alloc>::basic_string(std::basic_string<_Elem,_Traits,_Alloc> &&) throw()'
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Alloc=std::allocator<char>
]
c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstring(789): or 'std::basic_string<_Elem,_Traits,_Alloc>::basic_string(const _Elem *)'
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Alloc=std::allocator<char>
]
while trying to match the argument list '(const Item)'
Where is the problem? Thanks
EDIT: This is the constructor for std::string :
Item(const std::string str_value) {
m_data = new Data<std::string> (str_value);
m_type = V_STR;
}
std::string
from Item
:
template<typename T>
operator T () const {
//Check
if (this->m_data == nullptr)
return NULL;
// dynamic_cast m_data to point to "an Item of type T"
Data<T>* temp_data = dynamic_cast<Data<T>* > (m_data);
return temp_data->m_dataOfAnyType;
}
Upvotes: 0
Views: 830
Reputation: 11502
The reason why this is ambigious is due to your cast operator, which can cast an Item
into simply anything (atleast here you should have noticed that this is super ambigious).
A std::string
can be constructed through the copy constructor or with an char pointer (both only have 1 parameter, there are some more constructors but these are irrelevant for this). In this case the compiler does not know whether he should cast the Item
object to an char*
or to std::string
in order to construct a string (notice that when you return by value, a temporary is created).
I would recommend you to get rid of that casting operator, looks very hackish to me and Im sure that this is only one of many problems that will occur with that method. Define concrete casts.
Another possibility if you want to retain that operator is to define a toString()
method which is a lot cleaner than implicit casting anyways IMO.
The third possibility is to explicitely cast your Item
. You could then write:
return (std::string) item;
// or
return (char*) item;
Upvotes: 3