0

I want to write a template< class T > T string_to_T(const string& s) function that switches a string to a tempate T. T can be int/double/string and I write one as below:

template<class T> T Config::string_to_T(const string& s){
    T t;
    bool at_in = false;

    istringstream ist(s);
    ist >> t;

    return t;
}

But when there is a blank space in the string, it doesn't work. e.g. string = '1 2 3 4', returned t is string type and equals 4. How can I change to meet my need?

4

3 回答 3

3

See boost::lexical_cast. Basically, you need to specialize for the cases where >> doesn't do what you want. If you want string_to_T<std::string> to be a no-op, for example, you write a specialization:

template<>
std::string
string_to_T<std::string>( std::string const& s )
{
    return s;
}

For more complicated cases, you can forward to a functional object, and use partial specialization, but for the case you describe, this shouldn't be necessary.

While you're at it, you should probably think about error handling. What happens if you call string_to_T<int>, and the input is "abcd"? For that matter, if you call string_to_T<int> with "1 2 3 4", should the results be 1, or an error?

EDIT:

Having seen more of the comments to your question: you cannot change the return type at runtime (with certain very limited exceptions when returning a reference or a pointer within a class hierarchy). C++ is a statically typed language, every expression has a distinct type, determined at compile time. Supposing you could return two different types, how would you use the function, and how could the compiler detect the type errors it is required to detecte. The closest you can come is to return some sort of proxy, with implicit conversions to the various types, but the type you convert to would still be statically determined, according to what you do with the results: assign it to an int, and it will convert to an int, regardless of the contents of the string.

This type safety is a feature; detecting errors at compile time makes the code far more robust and sure than deferring the error detection to runtime. If you can do without this safety (non-critical application), and need the added flexibility of runtime typing, C++ is not the right language; you should be using something like Python.

EDIT 2:

In response to your comment, the solution would seem to be something along the lines of:

class ToStringHelper
{
    std::string myValue;
public:
    ToStringHelper( std::string const& value )
        : myValue( value )
    {
    }
    operator std::string() const
    {
        return myValue;
    }
    template <typename T>
    operator T() const
    {
        std::istringstream cvt( myValue );
        T results;
        cvt >> results;
        //  Error checking here...
        return results;
    }
};

ToStringHelper
string_to_T( std::string const& s )
{
    return ToStringHelper( s );
}

I use this exact pattern for configuration data (with errors triggering an exception).

于 2012-12-01T11:33:01.327 回答
0

The function you showed is doing a conversion from std::string to T. You specify T at compile time, you cannot change it at runtime.

If you want the type to depend on the value, you can use a Variant. See Boost.Variant for example (if you're working with Qt, there is QVariant). You can also use Boost.Any (difference between Variant and Any). For the conversion you might want to use Boost.Lexical_Cast. You will probably need to specify yourself that "1" -> 1 and "1 2 3 4" - > "1 2 3 4" in the variant/any. Be aware that all these functions will need you to add some code to handle the types. With variants, you can use visitors, a really powerful method to handle different types in variants.

于 2012-12-01T11:33:08.070 回答
0

Code to Convert any datatype to string:

#include <string>
#include <sstream>
#include <iostream>
using namespace std;


template <class T>
string toString(const T& t)
{
    std::stringstream ss;
    ss << t;
    return ss.str();
}


int main(void)
{


    string str;

    cout<<"Convert any datatype to string\n\n\n";

    int i=1234;
    str=toString(i );
    cout<<"int i= "<<str<<"\n";


  cout<<" \nPress any key to continue\n";
  cin.ignore();
  cin.get();

   return 0;
}
于 2012-12-01T11:44:59.907 回答