【问题标题】:How to write a generic function in C++ that takes as arguments both integers and strings and modifies them?如何在 C++ 中编写一个将整数和字符串作为参数并修改它们的通用函数?
【发布时间】:2012-10-04 17:29:25
【问题描述】:

我正在尝试编写一个函数,它接受一个字符串作为输入参数、三个可以是不同类型的输出参数(至少是这样的想法)和一个作为分隔符的字符。

输入字符串由指定的字符分隔,并且该函数将每个以字符结尾的字段按顺序分配给每个输出参数(目前它处理输入字符串,例如"a;bb;ccc",并且限制为三个输出只是争论,但这不是问题)。

例如,对于10;200;3000 之类的输入,我会分别得到102003000 作为第一个、第二个和第三个输出参数

输出参数必须是字符串或整数类型,但由于我对 C++(尤其是泛型编程)的了解有限,我在编写一个不关心它的泛型函数时遇到了麻烦。

我有以下代码:

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;}
    }
}

它适用于字符串,但显然不适用于整数。

我怀疑我在检查参数是否为空的地方出错了(以及我不知道的其他部分)。

你能帮我改进一下吗?

另外,我欢迎任何关于改进逻辑本身的想法(也许我需要使用可变参数模板以使参数的数量灵活,但是 如果 C++11 标准没问题,我必须咨询我们的技术主管)。

理想情况下,我希望避免出现两次完全相同的函数,但每种类型的签名不同(一个用于字符串和 一个用于整数)。

提前非常感谢!

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    我会将字符串拆分为字符串(如您所做的那样),然后将它们转换为所需的类型。

    您可以为此使用boost::lexical_cast,或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;
    }
    

    无论如何,如果您有 boost 可用,那么这是正确的方法

    【讨论】:

    • lexical_cast 是这样的,有更多的错误检查。主要是你可以在这里返回未初始化的res,如果arg的值在写入然后读取时没有解析。
    【解决方案2】:
    #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 会更安全!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      • 2017-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多