2012-09-03 71 views
3

我有一段簡單的代碼給了我一個編譯器錯誤。我沒有問題編譯和運行在Visual Studio下的Windows環境下,但現在在Linux下,使用gcc,我有問題。注意我正在使用gcc 4.4.5,並使用-std = C++ 0x指令。編譯器在使用GCC的代碼上出現錯誤代碼

該代碼片段位於頭文件file_handling.h中,該文件包含所有必需的庫(vector,string,fstream等)。變量'output_file'是LogFile對象的成員,並在其他地方正確檢查/實例化/ etc。代碼本身是平凡簡單,這就是爲什麼我很爲難:

template <typename T> void LogFile::put(std::string const & header, std::vector<T> const & data) { 

    output_file << header << " " << std::scientific << data[0] << std::endl; 

    for (std::vector<T>::const_iterator value = (data.begin()+1); value < data.end(); ++value) { 
      output_file << *value << std::endl; 
    } 

} 

編譯器狀態:

In file included from file_handling.cpp:2: 
file_handling.h: In member function 'void LogFile::put(const std::string&, const std::vector<T, std::allocator<_Tp1> >&)': 
file_handling.h:132: error: expected ';' before 'value' 
file_handling.h:132: error: 'value' was not declared in this scope 
make: *** [file_handling.o] Error 1 

爲什麼GCC沒有看到「價值」的原位聲明爲常量性?我已經嘗試了以下作爲完整性檢查:

template <typename T> void LogFile::put(std::string const & header, std::vector<T> const & data) { 
    std::vector<T>::const_iterator value; 
    output_file << header << " " << std::scientific << data[0] << std::endl; 

    for (value = (data.begin()+1); value < data.end(); ++value) { 
      output_file << *value << std::endl; 
    } 

} 

並且接收完全相同的編譯器報告。鑑於這看起來很簡單,並且在Visual Studio中運行良好,我對gcc和/或Linux環境有何遺漏或誤解?

+0

'#include '? –

+0

我假設矢量會爲我提供迭代器,因爲:: const_iterator是它的一個屬性,並且它一直在Visual Studio中工作。也就是說,我只是添加它來測試你的想法,不幸的是,這並沒有解決它。好主意,但。 – Avacar

+0

嘗試cbegin()而不是begin()。 begin()不適用於const迭代器。你還需要cend()而不是end()。 –

回答

5

正確的形式應該是:

template <typename T> void LogFile::put(std::string const & header, std::vector<T> const & data) { 

    output_file << header << " " << std::scientific << data[0] << std::endl; 

    for (typename std::vector<T>::const_iterator value = (data.cbegin()+1); value != data.cend(); ++value) { 
      output_file << *value << std::endl; 
    } 

} 

注加類型名,並從改變開始()和end()來CBEGIN()和CEND()。

當您使用模板類型時,需要typename。 begin()和end()不適用於const_iterators。

編輯︰顯然開始()和結束()將返回const_iterators。我從來沒有使用它們,因爲增加了清晰度和強制返回類型,所以總是使用cbegin()和cend()。對於他自己我猜。

注意:爲了簡化,您可以使用C++ 11中的新的auto關鍵字。

template <typename T> void LogFile::put(std::string const & header, std::vector<T> const & data) { 

    output_file << header << " " << std::scientific << data[0] << std::endl; 

    for (auto value = (data.cbegin()+1); value != data.cend(); ++value) { 
      output_file << *value << std::endl; 
    } 

} 
+0

這似乎解決了它。所以我猜Visual Studio對我來說很簡單,並且假定了typename關鍵字?我之前使用過這種語法,並且從不需要它,但僅限於VS2010版本的代碼。爲什麼需要typename關鍵字?爲什麼不清楚std :: vector :: const_iterator是一個類型? – Avacar

+0

@Avacar:不,現在還不清楚,因爲部分專業化。例如,如果'T'是'bool',事情會非常快速地變得非常怪異。 –

+0

啊,這是因爲模板。如果這已經是std :: vector :: const_iterator或類似的東西,它是否需要typename? [本文](http://pages.cs.wisc.edu/~driscoll/typename.html)似乎是解釋它,至少在模板化的函數和類中。這是因爲它在模板中,還是因爲矢量本身就是一個模板? – Avacar