templated subscript operator?

Started by
10 comments, last by Perost 19 years, 3 months ago
I'm writing a config class for my game, and you can use the subscript operator to retrive values, like:
int width = config["width"];
But since it returns strings this doesn't work. I thought that I'd overload the subscript operator so that it returns any type with the help of templates. I wrote this function:

template<class T> const T& Config::operator[] (const string &name)
{
	if(mReader[name].empty())
	{
		return StringTo<T>(mDefaults[name]);
	}
	return StringTo<T>(mReader[name]);
}
This function checks whether a value has been read from file, otherwise it returns a default value. StringTo<T> converts the string to type T. But this doens't work. I get "../game/Game.cpp:55: error: no match for 'operator[]' in 'Singleton<T>::Instance [with T = Config]()["width"]'" from the compiler when I'm compiling it. In normal templated functions you put <type> after the function name when calling it, but where to put it in this case? I've searched like a madman after a solution, but I can't find anything [crying]. If anyone know the answer to this, then I'd really appreciate some help.
Advertisement
The typical solution for this is to store values in a variant type, and return the variant type. If you want automatic conversion, then provide type conversion operators on the variant type. The biggest design question is what you should do when you ask for, say, an int, but the stored value is the string "christmas pudding". Return a default? Throw an exception? Crash?

If you don't know what a variant type is, it's basically a smart union. You can probably google for it.
enum Bool { True, False, FileNotFound };
Ok, I'll check that out.
Sorry, I can't really find anything useful on variant types. But I've experimented a bit with unions, and it seems like you can't use strings in them. Or am I wrong? If that it the case, then variants won't work, since I need strings. But back to my first question. Is there no way to make my function work as it is? Because if I'd change it to a normal function it would work. I could use something like this:
int width = config.get("width");

Of course you'd have to check that the stored value is valid.

Or you can add several functions

bool Read(int&   value, const char* string);bool Read(float& value, const char* string);...//and for the other 'types'bool Read(StringReadable& value, const char* string);


where StringReadable is an abstract base class that supports a function like

class StringReadable{public:   virtual void FromString(const char* string) = 0;};
Yes, I could do that. But what I need is a function that returns any type, so that I can use it in functions. I should propably have said this before, but I want to use it like:
SetVideo(config["width"], config["height"]);

Operator[] won't work because you'd have to call it explicitly, which makes it kind of pointless. Calling it would have to look like config.operator[]<returntype>("string"), because theres no other way to supply that template parameter. You can do it with a normal function. It will look like this:

SetVideo(config.getValue<int>("width"), config.getValue<int>("height"));
Thanks Deyja! That's what I wanted to know. I already knew about how to get it to work with normal functions like you showed, but not how to use the [] operator. And yes, it does indeed seem pointless to use it, so I might go with a normal function.
Another thing you *can* do (I'm not necessarily recommending this) is to have your operator[] return a type of your creation with conversion operators defined for primitive types.
For instance:
class Value {public:  Value() { }  Value ( const string& s ) : m_value(s) { }  operator int() const {    return StringTo<int> ( m_value );  }  operator double() const {    return StringTo<double> ( m_value );  }  operator string() const {    return m_value;  }  // Etc...private:  string m_value;};int main() {  Value value ( "42" );  int i = value;  cout << i << endl;  return 0;}



On a related topic: Is it possible to create an implicit conversion from one type to another without making a new member function in one of the types?

- Neophyte
Quote:Original post by Neophyte
On a related topic: Is it possible to create an implicit conversion from one type to another without making a new member function in one of the types?


Not as far as I know.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

This topic is closed to new replies.

Advertisement