Creating a class indexer operator[] allowing strin

2019-05-07 14:20发布

问题:

I want to create a class in c++. This class must manage with a collection. OK, no problem, I would like to use operator[] of course but, in this case, my wish is to index not by position, but by name ==> that means using a string indexer.

It seems that something of this kind is not so nice to my compiler:

// In hpp
class myclass {
   ...
   ...
   std::string operator[](const std::string& name);
}
// In cpp
std::string myclass::operator[](const std::string& name) {
   ...
}
// In main
myclass m;
std::string value = m["Name"];

Compiler tells me that he cannot solve this because operator[const char[5]] does not exists. OK OK I could figure this... Compiler thinks that by calling m["Name"] I'm trying to call an operator admitting a char* and not a string... ok Let's change the code with operator[] allowing a char* as parameter... nothing.

Can somebody tell me how to achieve such a result in c++ in a best practice way? I suppose that is a common problem to index by string and not by integer... Thank you.

回答1:

It should work fine. See this example which compiles and works ok for me:

#include <iostream>
#include <string>

class MyClass
{
    public:
        std::string operator[] (const std::string& key) { std::cout << key << std::endl; return key; }
};

int main()
{
    MyClass obj;
    std::string s = obj["50"];
    std::cout << s << std::endl;
}

And I see no reason it should not, since std::string has implicit constructor taking const char* so the conversion should be automatic.

Edit: From the comment it seems your problem was with your main beeing like this:

int main()
{
    MyClass obj();
    std::string s = obj["50"];
    std::cout << s << std::endl;
}

The reason:

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

[ Note: since () is not permitted by the syntax for initializer,

X a ();

is not the declaration of an object of class X, but the declaration of a function taking no argument and returning an X.

The form () is permitted in certain other initialization contexts (5.3.4, 5.2.3, 12.6.2). — end note ]



回答2:

The code that you have provided should compile okay (providing the operator is public and you terminate your class declaration with a ;). I suspect the compiler error is somewhere else.

Personally, I would use std::map<std::string, std::string> as the container class.

#include <string>
#include <map>
#include <assert.h>

int main()
{
    std::map<std::string, std::string> m;
    m["Foo"] = "Bar";
    m["Fez"] = "Baz";

    assert(m["Foo"] == "Bar");
    assert(m["Fez"] == "Baz");
}