简体   繁体   中英

How to write a generic function in C++ that takes as arguments both integers and strings and modifies them?

I'm trying to write a function that takes as an input argument a string, three output arguments that can be of varying types (at least that's the idea) and a char that is a delimiter.

The input string is delimited by the specified char and the function assigns each char-terminated field to each of the output arguments in order (at the moment it takes care of input strings such as "a;bb;ccc" and is limited to three output arguments only but that's not the problem).

For example with an input such as 10;200;3000 I'd get 10 , 200 and 3000 for the first, second and third output arguments respectively

The output arguments need to be of either string or integer types, but due to my limited knowledge of C++ (and in particular generic programming) I'm having trouble writing a generic function that doesn't care about that.

I have the following code:

template <typename T>
void parse_string (std::string &input, T &out1, T &out2, T &out3, const char delimiter)
{
    while (out3 == "")
    {
        std::string temp = input.substr(0, input.find(delimiter));
        input = input.substr(input.find(delimiter) +1);

        if (out1 == "") { out1 = temp;}
        else if (out2 == "") { out2 = temp;}
        else { out3 = temp;}
    }
}

and it works fine for strings but obviously not for integers.

I suspect I'm going wrong in the bits where I check if the argument is empty (among other parts I don't know about).

Could you please help me improve it?

Also, I would welcome any ideas on improving the logic itself (perhaps I'd need to go with the variadic templates to make the number of arguments flexible, but I'd have to check with our technical lead if C++11 standards are okay).

Ideally I'd like to avoid the situation where I have the exact same function twice but with a different signature for each of the types (one for strings and one for ints).

Many thanks in advance!

I would go with splitting the string into strings (as you do) and then converting them to required type.

You can use boost::lexical_cast for that, or std::stringstream

template <typename To, typename From>
To cast(const From &arg)
{
    std::stringstream s;
    s << arg;
    To res;
    s >> res;

    if (s.fail())
    {
        //throw some_exception();
    }

    return res;
}

In any case if you have boost available it is the right way to go

#include <algorithm>
#include <string>
#include <sstream>

template <typename T1, typename T2, typename T3>
void parse_string(const std::string& input, T1& out1, T2& out2,
                  T3& out3, char delimeter)
{
  std::istringstream is1(input);

  std::string field;
  for (int i = 0; std::getline(is1, field, delimeter) && i < 3; ++i)
  {
    std::istringstream is2(field);
    switch (i)
    {
    case 0: is2 >> out1; break;
    case 1: is2 >> out2; break;
    case 2: is2 >> out3; break;
    }

    if (is2.fail()) 
    {
      // do something about invalid type conversion?
    }
  }

  // up to you to decide what to do if the string has too
  // many or too few fields
}

lexical_cast would be safer tho!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM