[英](typedef) typename iterator are not working in c++,qt
我已經看到很多解決迭代器和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()) {
^
您不能在變量聲明中使用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)
您沒有修改列表-因此可以通過const引用來獲取它。 您也不必擔心容器的確切類型。 任何兼容STL的容器都可以。
使用std::is_same
代替typeid
。
textStream
類成員始終使用filePerson
文件。 pFile
從不用於任何東西。 這很可能是一個錯誤。
使用現有文件是不正確的-您實際上將其用於文件名存儲,並且不能確保保存失敗后數據也不會損壞。 請改用QSaveFile
。
該文件存儲文本數據,並且必須以文本模式打開。
適當的實現應如下所示-注意完整的簽名。
#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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.