наследование c ++ проблема Qt qstring - PullRequest
0 голосов
/ 09 июня 2009

У меня есть следующий код:

template <class T>
bool loadCSV (const QString &filename, map<T,int> &mapping){
    QFile boxfile;
    boxfile.setFileName(filename);
    QString line;
    QStringList list;

    if (!boxfile.open(QIODevice::ReadOnly)){
        cout << "Could not open box data file." << endl;
        return false;
    }

    QTextStream stream2( &boxfile ); 

    while (!stream2.atEnd()){
        line = stream2.readLine();
        list = line.split(',');
        mapping[list.front().toInt()]=list.back().toInt();      
    }

    return true;
}

Он берет файл CSV и вставляет его в:

map<int, int> mapping

структура. Теперь это сделано в качестве шаблона, так что я также могу использовать для вставки данных в

map<string, int> mapping

структура. Теперь, чтобы сделать это, необходимо изменить последнюю строку в цикле while, и я не уверен, что это лучший способ добиться этого.

Я мог бы придумать несколько способов:

  1. каким-то образом определить тип и использовать там какую-то условную строку (на самом деле я не уверен, возможно ли это, и если да, то как это сделать.

  2. добавить функцию класса в QStringList для этого.

Я попробовал вариант 2 и сделал это:

void QStringList::cInsert(map<int,int> &mapping){
    mapping[this->front().toInt()]=this->back().toInt();
}

void QStringList::cInsert(map<string,int> &mapping){
    mapping[(this->front()).toAscii()]=this->back().toInt();
}

Это не сработало, так как мне также нужно было определить эти функции в классе QStringList, так что это может стать немного запутанным. Вместо. Я пытаюсь наследовать от QStringList:

class myQStringList: public QStringList{
    public:
        void cInsert(map<int,int> &mapping);
        void cInsert(map<string,int> &mapping);
};

void myQStringList::cInsert(map<int,int> &mapping){
    mapping[this->front().toInt()]=this->back().toInt();
}

void myQStringList::cInsert(map<string,int> &mapping){
    mapping[(this->front()).toAscii()]=this->back().toInt();
}

А затем измените код:

template <class T>
bool loadCSV (const QString &filename, map<T,int> &mapping){
    QFile boxfile;
    boxfile.setFileName(filename);
    QString line;
    myQStringList list;   

if (!boxfile.open(QIODevice::ReadOnly)){
    cout << "Could not open box data file." << endl;
    return false;
}

QTextStream stream2( &boxfile ); 

while (!stream2.atEnd()){
    line = stream2.readLine();
    list = line.split(',');
        list.cInsert(mapping);
}

return true;}

НО. Я получаю ошибку в связи с назначением line.split / list:

main.cpp:123: error: no match for 'operator=' in 'list = QString::split(const QChar&, QString::SplitBehavior, Qt::CaseSensitivity) const(((const QChar&)(&QChar(44))),  KeepEmptyParts,  CaseSensitive)'

Я не уверен, что это за ошибка, и не уверен, что это связано с тем, что оператор присвоения / копирования не наследуется?

А по отношению к новому классу я получаю эту ошибку:

main.cpp:104: error: no match for 'operator[]' in 'mapping[QString::toAscii() const()]'
c:/qt/mingw/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_map.h:332: note: candidates are: _Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = std::string, _Tp = int, _Compare = std::less<std::string>, _Alloc = std::allocator<std::pair<const std::string, int> >]
main.cpp: In function `bool loadCSV(const QString&, std::map<T, int, std::less<_Key>, std::allocator<std::pair<const T,int> > >&) [with T = int]':

Что я просто не понимаю. Кто-нибудь может объяснить, пожалуйста?

Кроме того, я не уверен, правильно ли я поступаю, и был бы признателен за совет относительно этого. Спасибо.

Ответы [ 3 ]

2 голосов
/ 09 июня 2009

Я бы переместил преобразование из QString в тип T за пределы вашей функции. Поэтому есть что-то вроде:

template< typename T>
struct converter { };

template<>
struct converter< int>
{
static int convert( const QString& source)
{
    return source.toInt();
}
};

template<>
struct converter< std::string>
{
static std::string convert( const QString& source)
{
    return source.toStdString();
}
};

template< typename T>
T convertFromString( const QString& source)
{
    return converter<T>::convert( source);
}

Затем используйте эту функцию преобразования в вашем цикле (внутри while):

Вместо

mapping[list.front().toInt()]=list.back().toInt();   

запись:

mapping[ convert<T>(list.front())]=list.back().toInt();

Примечание: Преобразователь класса (и две его специализации) определены, так что функцию convert можно использовать в качестве функции шаблона (аналогично static_cast или boost :: lexical_cast, если хотите).

Я не пытался скомпилировать код. Это просто идея.

1 голос
/ 18 июня 2009

Когда речь идет о файлах CSV, Qt предоставляет удобную функциональность через функцию QString :: section Итак, чтобы найти необходимые столбцы, я обрабатываю заголовок следующим образом:

int AmountInd = (line.left(line.indexOf("Amount")).count(',');

чтобы получить индекс этого столбца. Затем для следующих строк я извлекаю подстроку этого столбца:

QString AmountStr = (line.section(',', AmountInd, AmountInd);
double Amount = AmountStr.toDouble();

Надеюсь, вы найдете функцию секции полезной; -)

0 голосов
/ 09 июня 2009

Я решил проблему путем явного приведения:

list = (const myQStringList&) line.split(',');
void myQStringList::cInsert(map<string,int> &mapping){
    mapping[(string)(this->front()).toAscii()]=this->back().toInt();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...