c++ - 如何在 C++ 中将字符串转换为模板化类型

标签 c++ parsing templates type-conversion

我想以通用方式读取和解析 C++ 中的文本文件。该文件始终由键值对组成,每行一个。键和值都被模板化了。我预见键和值始终是基本类型(int、float、string)。

我的问题是我不知道如何创建将键或值字符串转换为正确类型的方法。

我尝试了以下方法:

template<class Key, class T> inline
void EventReportReader<Key, T>::validateFileFormat()
{
    // Read file line by line and check that the first token is of type Key and the second one of type T

    std::string line;
    try {
        boost::regex re( "(\\S+)\\s+(.*)" );
        while( getline( inStream_, line ) ) {
            boost::cmatch matches;
            if( boost::regex_match( line.c_str(), matches, re ) ) {
                std::cout << re << " matches " << line << std::endl;
                std::cout << "   1st : " << matches[1] << "\n   2nd : " << matches[2] << std::endl;
                // test types
                Key *k = dynamic_cast<Key*>(&matches[1]);
                T t = dynamic_cast<T>(matches[2]);
            }
        }
    }
    catch( boost::regex_error& e ) {
        // todo problem with regular expression, abort
    }
}

该方法的使用如下:

// This in turn calls the method validateFileFormat
EventReportReader<float, int> reader( testFileName );

结果是

/home/vonhalle/dev/EventBasedReport/libs/event_based_report/EventReportReader.h:121:60: error: cannot dynamic_cast ‘(const boost::sub_match*)matches.boost::match_results::operator[] with BidiIterator = const char*, Allocator = std::allocator >, boost::match_results::const_reference = const boost::sub_match&’ (of type ‘const struct boost::sub_match’) to type ‘float’ (target is not pointer or reference to class) /home/vonhalle/dev/EventBasedReport/libs/event_based_report/EventReportReader.h:122:53: error: cannot dynamic_cast ‘matches.boost::match_results::operator[] with BidiIterator = const char*, Allocator = std::allocator >, boost::match_results::const_reference = const boost::sub_match&’ (of type ‘const struct boost::sub_match’) to type ‘int’ (target is not pointer or reference)

我应该怎么做? 有可能吗?

编辑: 如果模板是

,文件可能看起来像这样
1.14 5
2.34 78
0.56 24

或者如果模板是

23 asdf
45 2222
1 bbbb

编辑2:

上面的问题陈述是部分错误的。键永远不是字符串,值可以是字符串。因此,第一个空格之前的是键,其余的是值。很抱歉这个错误。

最佳答案

我认为你的基本方法是错误的。
您似乎在尝试使用模板元编程来实现您的目标。
这可能不是一个好主意。

更简单的方法是使用 C++ 流。
这些流对象已经知道如何读取所有基本类型。任何想用 C++ 做任何事情的人都会添加适当的输入和输出运算符来流式传输他们的类;所以它是非常普遍的,你将能够读取任何类型作为键和值(限制它必须适合一行)。

因此,现在您只需要使用标准模板逻辑来定义一个运算符,该运算符将在一行中读取两个不同类型的对象。

试试这个:

#include <string>
#include <memory>
#include <fstream>
#include <sstream>
#include <vector>
#include <iterator>
#include <algorithm>

// These can be any types.    
typedef std::string   Key;
typedef int           Value;

// The data type to hold the data.
template<typename K,typename V>
class Data: public std::pair<K, V>
{

};

这是从文件的一行中读取一条记录的代码:
请注意,数据类型 Data 和此输入运算符都是模板化的,因此可以准备任何对象的键/值对(只要这些对象知道如何流式传输自己)。

template<typename K,typename V>
std::istream& operator>>(std::istream& stream, Data<K,V>& data)
{
    // Read a line into a local string.
    std::string  line;
    std::getline(stream,line);

    // convert the line into a stream and read the key/value from the line
    std::stringstream  linestream(line);
    linestream >> data.first >> data.second;


    // If the linestream is bad, then reading the key/value failed
    // If reading one more `char` from the linestream works then there is extra crap in the line
    // thus we have bad data on a line.
    //
    // In either case set the bad bit for the input stream.
    char c;
    if ((!linestream) || (linestream >> c))
    {
        stream.setstate(std::ios::badbit);
    }
    // return the stream.
    return stream;
}

现在使用它就意味着使用流:

int main()
{
    // The input file
    std::ifstream      file("Plop");

    // We will convert the file and store it into this vector.
    std::vector<Data<Key,Value> >  data;

    // Now just copy the data from the stream into the vector.
    std::copy(std::istream_iterator<Data<Key,Value> >(file),
            std::istream_iterator<Data<Key, Value> >(),
            std::back_inserter(data)
            );
}

注意:在上面的示例中,键必须是单个单词(因为它是使用字符串读取的)。如果你想要一个包含空格的字符串形式的键,你需要做一些额外的工作。但这是另一个问题的主题。

关于c++ - 如何在 C++ 中将字符串转换为模板化类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7254009/

相关文章:

java - 如何从 java 中的字符串中删除无效的 unicode 字符

Django:无法加载模板标签

c++ - 使用chrono C++与时间进行比较

java - SimpleDateFormat 和解析 : parse doesn't fail with wrong input string date

c++ - opengl 3.1 纹理未加载

c++ - 解构固定长度二进制/alpha 消息的最快方法是什么?

python - 在 Python 中使用可变数量的 .format() 参数进行格式化

Javascript 模板还是其他解决方案?

c++ - 复制构造函数是否仍然参与复制初始化?

c++ - 虽然不是新线