Martin
Martin

Reputation: 336

Piping from Istringstream into templates

I have the following questions: I have a map from string to string which is called psMap. I.e. psMap["a"]="20", psMap["b"]="test", psMap["c"]="12.5", psMap["d"]="1" (true) so the map stores string-expressions of various basic-data types.

The following function foo should (given a key), copy the mapped value to a corresponding type variable, i.e;

int aa;
foo("a", aa); 
=> aa=20.

Explicitly, I want to have one function for all possible data-types (so no manually cast), so I tried with templates exploiting the automatic conversion of istringsteram, namely

template<class PARAMTYPE>
void foo(string _name, PARAMTYPE& _dataType) {
    PARAMTYPE buff;
    istringstream(psMap[_name]) >> buff;
    _dataType = buff;
}

The problem is, that the ">>" operation gives an error: Error: no match for »operator>>« in »std::basic_stringstream<char>((* ....

What is going wrong here? Does the stringstream not recognize the correct data type and tries to pipe into an abstract type of "template"? How could I make my code work?

Tank you for your effort :)

Upvotes: 0

Views: 249

Answers (3)

James Kanze
James Kanze

Reputation: 153977

You've created a temporary std::istream, which means that it cannot bind to a non-const reference. Some of the >> are member functions, and they will work, but others are free functions with the signature:

std::istream& operator>>( std::istream&, TargetType& );

and these will not work (or even compile).

To avoid the problem either Just declare an std::istringstream and use it, or call a member function on the temporary which does nothing, but returns a (non-const) reference:

std::istringstream( psMap[name] ).ignore(0) >> buff;

(Personally, I find the separate variable more readable.)

Upvotes: 1

utnapistim
utnapistim

Reputation: 27375

Try this implementation:

template<class R>
R get_value(const std::string& name) {
    R result{};
    std::istringstream buffer{psMap[name]};
    buffer >> result;
    return result;
}

client code:

int x  = get_value<int>("a");

Also, do not use identifiers starting with an underscore. That is reserved for library implementers.

Upvotes: 0

Wojtek Surowka
Wojtek Surowka

Reputation: 21003

You use reference as the template argument, so if you call

foo("a", aa);

without '& it should be fine (the way you tried the operator>> for pointer was needed). You also need to modify the last template line:

_dataType = buff;

Upvotes: 0

Related Questions