The main problem is that returning multiple types is not great design. Its okay for scripting languages that are just doing web-stuff. But for serious systems programming its way to dangerous.
The fact that it can't be done in C++ is a feature, not a limitation.
However, I can't help but think that using void* would be a considerably shorter and better solution than this. You just need to ensure that you don't mess up on your explicit type casts.
Face it: those "evil" things are "evil" for a reason, and it's not because they're worse solutions to all given problems.
Thank you all, I went to bed shortly after my last post which is why it took me so long to reply and I also have somewhere to go later so I wouldn't recommended checking back between 08-18. Incedently I'm a guy so you don't need to refer to me as he/she. It's 5:40 my end so I wom't try any suggestions until later on in the day. If I do get it working then I'll be sure to post it for everyone to reference.
They are when they prevent you from making mistakes. Any programmer would rather have compiler errors than runtime errors.
The reason why void* is evil is because it sidesteps the compiler's [very involved] type systems and removes all the safeguarding. So if when you screw up, there's no warning or error from the compiler, and your program starts crashing, leaving you to debug thousands of lines code looking for a bad cast.
You just need to ensure that you don't mess up on your explicit type casts.
I like to say that the best programmer is not the one who makes the least mistakes; it's the one who makes it the hardest for himself to make them, and minimizes the cost of making them.
Once you accept that you will make mistakes, you'll learn to work with that nature, not against it.
if C++ had an option for weak typing...
...it would be even harder to keep track of things.
They're easy to screw up, indeed, however that doesn't mean one should never use them.
There's very few cases where void * is an absolute necessity.
Right now I can only think of dynamic linking, "strongly" opaque pointers, and very specific cases where you're writing portable code and want to avoid conditional compilation (which would make it a special case of an opaque pointer).
I think that's about it.
As you might have noticed the function I'm creating is to use an array of Options with varying value types (reason for the type parameter), in the end I'll have 2 functions to handle the data: 1st will return the data, 2nd will change the data (this function I'll use when loading user options from a file). The 1st function's returned data will be handled by the main function by reading the type parameter before using it - this way I get the data I need and handle it in the approriate way.
I'll go with Disch's approach but (1) I won't use unions and (2) to make up for the (possibly) big size of the ReturnValue type I'll pass it as a reference instead of directly returning it.