2012-09-03 70 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