-
July 2nd, 2009, 03:46 AM
#1
Different return type depending on data
I'm designing a class where there's a method that should return a different data type depending on certain circunstances.
Specifically, I'm reading from a text file. If the data found are strings of characters, I'd like to return a vector of strings. On the other hand, I'd like to return a vector of floats if the data are numbers.
template <typename T>
vector<T> funcion(string typeConversion){
if (typeConversion== 'String')
//...
return list<string>
else if (typeConversion == 'Number')
//...
return vector<float>
}
I don't think this is possible with C++ (in Python, for instance, I think that methods can return every data type).
Do you know any alternative to solve my problem?
Thanks!
-
July 2nd, 2009, 04:09 AM
#2
Re: Different return type depending on data
Originally Posted by metzenes
Specifically, I'm reading from a text file. If the data found are strings of characters, I'd like to return a vector of strings. On the other hand, I'd like to return a vector of floats if the data are numbers.
OK.
I don't think this is possible with C++
Instead of thinking of other languages, you should concentrate on how to solve this using C++.
You are given a string, and you are doing something different when a different string is given to you. That is basically what this all boils down to. The problem is that your mindset is on "returning" something, when it could be solved by redesigning your code so that it doesn't need to return anything specific. Maybe that entire testing of the string shouldn't be in the template to begin with.
Second, your example is faulty -- you are returning a list<T>, when the return type is vector<T>.
But in general it is possible in C++ using something called "compile-time polymorphism" or policy-based programming. What you are looking for is something called "template specialization". Do a search on CodeGuru, and you will see samples of this.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; July 2nd, 2009 at 04:19 AM.
-
July 2nd, 2009, 10:11 PM
#3
Re: Different return type depending on data
You should be able to do this by returning a union of different datatypes similar to the VARIANT structure. See here - VARIANT and VARIANTARG
-
July 2nd, 2009, 10:54 PM
#4
Re: Different return type depending on data
One solution (which I'm using a variation on myself at the moment) is to define a common base class Base such that Derived<string> and Derived<float> both inherit from it. Then you can specify the return type as a Base*, but actually return a pointer to whichever type you actually have.
Of course, as with all things polymorphic, you have dynamic memory forced on you a bit more than you'd probably like.
-
July 2nd, 2009, 11:52 PM
#5
Re: Different return type depending on data
There are two basic problems.
First, you can't overload a function, even by templates like this, based only on the return type.
Second, by the time you can supply a string, you already MUST know the return type, obviating the necessity of the string specifying the return type.
What you can do is overload using a reference...
template <typename T> funcion( T & i ) {... }
Consider the calling code. If you're going to instantiate the function on behalf of a float, your call, if it were even possible, would have to be something like:
float v = convert<float>( floatstring );
Why would you want to provide a string stating the return type? It's redundant information. You could not determine the type of the return value based on the template - that is v isn't going to modulate it's type in this context, or any context in which you make a call (though the variant type is theoretically 'any' type, it is, itself, a type).
Since you can't overload based on return type, you would:
float v;
convert( v );
However, the context of this call is what's important. Is your reason for wanting a string based on some user input selection?
I'd need more to go on before I drift off into a tangent outside you're interest. What we need to know in order to be of help is why you're doing this and what the context is, how are you deciding what type to convert to?
If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).
-
July 3rd, 2009, 02:08 AM
#6
Re: Different return type depending on data
Thank you all for all your interesting and helping answers!
I'll explain more in detail what I'm trying to do:
I'm reading a text file that includes loads of data ordered by columns. Each column contains a different kind of data (it can be text or numbers). My method should return a vector (or any other data structure) containing the data from the column provided.
Depending on what kind of data the column has, I'd return a vector<string> or vector<float>, for instance.
vector<T> method(string column_name){
ReadColumnFromFile()
if Column is text
return vector<string>
else if Colum is numbers
return vector<float>
}
I think VARIANT it's a good option for solving that.
Another problem is to know when the information should be a string or a number (float, for example). When I read from the file I always get a string. I thought about using atof() to convert the string to a float; if it works it'll be a number, if not it'll be a string. What do you think?
-
July 3rd, 2009, 04:17 AM
#7
Re: Different return type depending on data
Originally Posted by metzenes
I think VARIANT it's a good option for solving that.
I think it would be better to go with Lindley's suggestion.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
July 3rd, 2009, 01:56 PM
#8
I second that..
A base column container, or a container of a base type, or a template derivative from a base type - all applicable.
The point here is that your puzzle should be turned inside out.
Instead of concentrating on obtaining a return type out of the column data, aimed at suiting the caller's need for a particular type, turn the puzzle inside out and call a generic operation which performs a callback based on the derived type.
Consider each of the reasons for the call, for which the ultimate type is required. It could be a calculation, it could be for display, it could be to obtain the data for another use. Whatever they are, form a collection of these based on the generic notion of the column. Let the virtual derivative deal with the actual method, which in turn calls an overload to respond appropriately based on type.
For example, say the purpose is calculation. Create a small collector, something like:
Code:
class sum_collector
{
private:
float sum;
public:
sum_collector() : sum( 0.0f ) {}
accumulate( float &f ) { sum += f; }
};
create a sum_collector and pass it to a generic function which takes (or operates on) a column, without respect to type.
The virtual function which a "float" version responds with would call accumulate with it's float member, but if it's a string it would ignore the call.
The visitor pattern deals with this issue in a double dispatch scenario. Say, for example, your columns also included int and double types. In order to perform some operations with a combination of int, double and/or float, you'd need the visitor pattern, or some form of double dispatch to solve the issue.
There are various ways to consider and solve the puzzle, and virtual functions are generally at the heart of it. It is genuinely a mistake to insist the puzzle be solved from the caller's perspective. The caller should not have to know the type, it should be able to consider the call on whatever type - let the virtual derivative figure that out, and let it make a callback to complete the appropriate type-oriented behavior.
If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).
-
July 3rd, 2009, 07:44 PM
#9
Re: Different return type depending on data
Originally Posted by metzenes
I'll explain more in detail what I'm trying to do:
I'm reading a text file that includes loads of data ordered by columns. Each column contains a different kind of data (it can be text or numbers). My method should return a vector (or any other data structure) containing the data from the column provided.
SQL libraries have already solved this problem in one sense: They require the calling code to know what type of data each column is expected to contain. So for instance, you could write getFloatColumn("MyColumnName") or getStringColumn("MyColumnName2"). The idea being that if you encounter some type of data other than what you're expecting, you just throw an exception.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|