I am creating a class Item, and each Item is a key/value pair. Also, each Item may also contain subitems:
#include 
#include 
#include 
class Item
{
    private:
        std::string key;
        unsigned int value;
        std::vector-  subitems;
 
 
 public:
 
 Item( const std::string& key = "", const int& value = 0 )
 : key( key ), value( value ){ };
 
 
 public:
 // Search or Create new SubItem.
 Item& operator[]( const std::string& key )
 {
 for( auto& subitem : subitems )
 if( subitem.key == key )
 
 return subitem;
 
 subitems.push_back( Item( key ));
 return subitems.back( );
 }
 
 
 public:
 // Assign new value to Item.
 Item& operator=( const int& value )
 
 {
 this->value = value;
 return *this;
 }
 
 
 public:
 // Get value from Item.
 operator unsigned int( ) const
 {
 
 return value;
 }
 };
 
 
 
 int main( void )
 {
 Item item;
 
 
 
 item["sub"] = 42;
 unsigned int sub = item["sub"];
 
 
 std::cout << std::to_string( sub ) << std::endl;
 return 0;
 }
 
When I try to compile this, I get:
error: ambiguous overload for ‘operator[]’ (operand types are ‘Item’ and ‘const char [4]’)
If I create a member method unsigned int Get() instead of operator int() it does compile. But I wanted the class to work the same way that std::map works:
#include How can I get it working?
Thanks!
Answer
The problem is that you are conflicting with the builtin operator[](unsigned int, const char *) (yes, that's a thing). 
Implicitely converting the operand to a std::string or implicitely converting the Item to an unsigned int before applying the operator[] is equivalent for the compiler, so it can't choose between the two.
You can work around this by adding an explicit const char* overload to your class' operator[] that defers to your std::string implementation.
// Search or Create new SubItem.
Item& operator[]( const char* key ) {
    return (*this)[std::string(key)];
}
 
No comments:
Post a Comment