【问题标题】:Compiler Error on code with GCC that worked on Windows在 Windows 上运行的 GCC 代码编译器错误
【发布时间】:2012-09-03 03:01:13
【问题描述】:

我有一段简单的代码给我一个编译器错误。我在 Visual Studio 下的 windows 环境中编译和运行它没有问题,但现在在 linux 下,使用 gcc,我遇到了问题。注意我正在使用 gcc 4.4.5,并使用 -std=c++0x 指令。

此代码 sn-p 位于头文件 file_handling.h 中,其中包含所有必需的库(vector、string、fstream 等)。变量 'output_file' 是 LogFile 对象的成员,并在其他地方得到正确检查/实例化/等。代码本身非常简单,这就是我难过的原因:

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 没有将 'value' 的原位声明视为 const_iterator?我已尝试以下方法作为健全性检查:

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 环境有什么遗漏或误解?

【问题讨论】:

  • 我曾假设 vector 会为我引入迭代器,因为 ::const_iterator 是它的属性之一,并且它一直在 Visual Studio 中工作。也就是说,我只是添加它来测试您的想法,不幸的是,这并没有解决它。不过是个好主意。
  • 尝试 cbegin() 而不是 begin()。 begin() 不适用于 const 迭代器。您还需要 cend() 而不是 end()。
  • 真的吗? Cplusplus.com 建议 begin() 可以在需要时返回一个 const 迭代器。无论如何,我尝试了你的建议,它仍然给出了相同的编译器错误。

标签: c++ gcc for-loop compiler-errors


【解决方案1】:

正确的形式应该是:

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;
  }

}

注意 typename 的添加,以及从 begin() 和 end() 到 cbegin() 和 cend() 的变化。

当您使用模板类型时,typename 是必需的。 begin() 和 end() 不适用于 const_iterators。

编辑:显然 begin() 和 end() 将返回 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;
  }

}

【讨论】:

  • 这似乎已经解决了。所以我猜 Visual Studio 对我来说很容易,并假设 typename 关键字?我以前使用过这种语法,但从来不需要它,但只在 VS2010 版本的代码上使用。为什么需要 typename 关键字?为什么不清楚 std::vector::const_iterator 是一种类型?
  • @Avacar:不,不清楚,因为部分专业化。例如,如果Tbool,那么事情很快就会变得非常奇怪。
  • 啊,是模板的原因。如果这是 std::vector::const_iterator 或类似的东西,它对 typename 的需求是否相同? This article 似乎在解释它,至少在模板化函数和类中。这是因为它在模板中,还是因为 vector 本身就是一个模板?
  • @Avacar:见my previous question
猜你喜欢
  • 2010-09-17
  • 1970-01-01
  • 2011-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多