(typedef)typename迭代器在c++、qt中不起作用

(typedef) typename iterator are not working in c++,qt

本文关键字:qt 不起作用 c++ typedef typename 迭代器      更新时间:2023-10-16

我看到迭代器、typedef和typename已经解决了很多问题。没有任何答案对我有帮助。

我已经试过了,没有任何东西和

typename QLinkedList<T>::iterator iter = TList->begin();

typedef typename QLinkedList<T>::iterator iter = TList->begin();

整个模板:

template <class T>
void DataManager::saveObject(QLinkedList<T> * TList) {
QFile * pFile;
// choose a file in case of class
if( typeid(T) == typeid(Medium) ) pFile = &fileMedium;
else                              pFile = &filePerson;
// open the choosen file
pFile->open(QIODevice::WriteOnly | QIODevice::Truncate);
// open the textSteam to write
textStream.setDevice(&filePerson);
// write each information to the textstream/file
if(!TList->isEmpty())
// set iterator                         
typename QLinkedList<T>::iterator iter = TList->begin();
while(iter != TList->end()) {    // <--- Err: not declared !
textStream << iter->getDataInCSV();
++iter; //move iterator to next
}
// close the file
pFile->close();
}

错误:

error: 'iter' was not declared in this scope
while(iter != TList->end()) {
^
  1. 您没有修改列表,因此使用const引用。您也不需要担心容器的确切类型。任何STL兼容的容器都可以。

  2. 使用std::is_same而不是typeid

  3. textStream类成员始终使用filePerson文件。pFile从不用于任何用途。这很可能是个bug。

  4. 使用现有文件是不正确的——你基本上是将其用于文件名存储,而且如果保存失败,它不会确保数据不会被损坏。请改用QSaveFile

  5. 该文件存储文本数据,必须以文本模式打开。

正确的实现如下所示-注意完整的签名。

#include <type_traits>
// Returns true upon success, false upon failure
template <class T> bool DataManager::saveObject(const T& data) const {
using value_type = typename T::value_type;
bool const isMedium = std::is_same<value_type, Medium>::value;
bool const isPerson = std::is_same<value_type, Person>::value;
static_assert(isMedium || isPerson,
"The data must be of either Medium or Person type");
const QFileDevice &aFile = isMedium ? fileMedium : filePerson;
Q_ASSERT_X(!aFile.isOpen(), "saveObject", "The file must not be open");
QSaveFile file(aFile.fileName());
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
{
QTextStream stream(&file);
for (auto &item : data)
stream << item;
stream.flush();
if (stream.status() != QTextStream::Ok)
return false;
}
return file.commit();
}

不能在变量声明中使用typedef

您也不需要使用typename,因为您不是定义依赖于模板参数指定的另一个类型的类型。

您只是试图声明一个现有类型的变量,所以只需按原样使用该类型,例如:

// use a const_iterator to avoid detach-ing the list while iterating...
QLinkedList<T>::const_iterator iter = TList->cbegin();

或者,如果您使用C++11或更高版本,您可以将其简化为:

auto iter = TList->cbegin();

无论哪种方式,您都会得到"未在此范围内声明"错误,因为您的if块上没有一对大括号:

if(!TList->isEmpty())
{ // <-- add this!
// set iterator                         
QLinkedList<T>::const_iterator iter = TList->cbegin();
// or: auto iter = TList->cbegin();
while(iter != TList->cend()) {
textStream << iter->getDataInCSV();
++iter; //move iterator to next
}
} // <-- add this!

如果没有额外的大括号,您的原始代码在功能上与以下代码相同:

if(!TList->isEmpty()) {
// set iterator                         
QLinkedList<T>::iterator iter = TList->begin();
}
while(iter != TList->end()) {    // <--- iter is not in scope here!
textStream << iter->getDataInCSV();
++iter; //move iterator to next
}

正如您所看到的,while循环不在if语句的主体中,因此iter变量确实不在可供while循环使用的范围中。

如果您使用的是C++11或更高版本,请考虑使用基于范围的for循环,这样您就根本不必处理迭代器:

// write each information to the textstream/file
for (const T &item : qAsConst(*TList)) {
textStream << item.getDataInCSV();
}

或者:

// write each information to the textstream/file
for (const auto &item : qAsConst(*TList)) {
textStream << item.getDataInCSV();
}

或者,您可以使用Qt自己的foreach扩展:

// write each information to the textstream/file
foreach (const T &item, *TList)
textStream << item.getDataInCSV();

附带说明一下,Qt容器通过引用计数实现写时复制语义,因此它们通过值传递非常有效,不需要通过指针传递,例如:

void DataManager::saveObject(QLinkedList<T> TList)

尽管我可能会使用const引用,因为这是绕过一个你不会修改的对象的首选方式:

void DataManager::saveObject(const QLinkedList<T> &TList)