开发者

Templated operator[]... possible? Useful?

Could you have:

template <class T>
const T &operator[] (unsigned int x)

My thinking was if you have a map<string,strin开发者_JAVA百科g> it would be nice to have a wrapper class which lets you do:

obj["IntVal"]="12";
obj["StringVal"]="Test";

int i = obj["IntVal"];

How close to this can we actually get in C++? Is it worth the pain?


You can also do

class Class {
  struct Proxy {
    template<typename T> T as() { ... }
    template<typename T> operator T() { return as<T>(); }
  private:
    Proxy(...) { ... }
    Proxy(Proxy const&); // noncopyable
    Proxy &operator=(Proxy const&);
    friend class Class;
  };

public:
  Proxy operator[](std::string const& s) { ... }
};

Class a;
int i = a["foo"];
int i = a["foo"].as<int>();

T will be deduced to whatever the to be initialized object is. And you are not allowed to copy the proxy. That said, i prefer an explicit as<T> function like another one proposed too.


You can't - in:

int i = obj["IntVal"]; 

the actual type of T can't be inferred from the context since the return type isn't part of the function signature.

Moreover, storing integer values as strings is not considered as best practices, due to memory and performance considerations ;-)


Not worth it.

Templating the return type means you'd have to explicitly specify the template parameter when you call it. Something like this, maybe I have the syntax wrong:

int i = obj.operator[]<int>("IntVal");

C++ does not deduce template parameters from what you assign the result of the call to, only from the parameters you call the function with.

So you might as well just define a normal function:

int i = obj.get<int>("IntVal");

Or in this case, either do this or implement get using this:

int i = boost:lexical_cast<int>(obj["IntVal"]);

As Amit says, you could define operator[] to return a type which can be converted either to int or to other types. Then your example code can be made to compile without the explicit lexical_cast.


Have you looked at boost variant? Is this what you're looking for?


Well, what you wrote in your sample code doesn't match the question. Right now, you only have the return type templated.

But if you wanted to do something like:

template <class T>
const T &operator[const T& x]

that's valid, though maybe not terribly useful.


A map already provides an overloaded operator[] that does most of what you want. The thing you seem to want that's missing is implicit conversion from a string that happens to contain digits to an integer. One of the fundamental characteristics of C++ is static typing, which says that shouldn't be allowed -- so it's not. It'll be happy to do that conversion if you want, but you'll have to ask for it:

int i = lexical_cast<int>(obj["IntVal"]);

Alternatively, you could create a string-like class that supported implicit conversion to int. Personally, I'd advise against that. I don't object to implicit conversions nearly as strongly as many people do, but that still strikes me as a pretty lousy idea, at least for most general use.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜