4

我编写的一些代码遇到了一个非常讨厌的问题。我发现其他人在 stackoverflow 上遇到了同样的问题,我尝试了解决方案,但没有一个对我有用。

我对我正在使用的几种常见 STL 类型进行了 typedef,除了我尝试对地图进行 typedef 时,其他都没有任何问题。在测试程序中包含我的标头时,我收到“some_file.h:83: error: expected initializer before '<' token”错误。

这是标头(some_file.h)的重要部分:

#ifndef SOME_FILE_H
#define SOME_FILE_H
// some syntax-correct enums+class prototypes
typedef std::string str;
typedef std::vector<Column> col_vec;
typedef col_vec::iterator col_vec_i;
typedef std::vector<Row> row_vec;
typedef row_vec::iterator row_vec_i;
typedef std::vector<str> str_vec;
typedef str_vec::iterator str_vec_i;
typedef std::vector<Object> obj_vec;
typedef obj_vec::iterator obj_vec_i;
typedef std::map<Column, Object> col_obj_map; // error occurs on this line
typedef std::pair<Column, Object> col_obj_pair;

some_file.cpp 中的包含有:

#include <utility>
#include <map>
#include <vector>
#include <iostream>
#include <string>
#include <stdio.h>
#include <cc++/file.h>
#include "some_file.h"

测试文件按顺序仅包含字符串、向量和我的文件。它有一个 main 方法,它只是做一个 hello world 之类的事情。

有趣的是,我很快将一个模板类放在一起以查看问题出在哪里(将“ std::map<Column...”替换为“ hello<Column...”)并且它没有问题地工作。

如果您使用的类没有 ' <' 运算符,我已经创建了映射所需的运算符重载。

4

4 回答 4

14

您遇到此问题是因为编译器不知道地图是什么。它不知道,因为尚未包含地图标题。您的标头使用 STL 模板:字符串、向量、映射和对。但是,它没有定义它们,也没有提及它们的定义位置。您的测试文件在 map 上而不是在 string 或 vector 上的原因是您在 some_file.h 之前包含了 string 和 vector 头,因此定义了 string 和 vector,但 map 没有。如果您包含地图的标头,它会起作用,但它可能会抱怨对(除非您的特定 STL 实现在地图的标头中包含对)。

通常,最好的策略是为您在自己的标题中使用的每种类型包含适当的标准标题。所以 some_file.h 至少应该有这些头文件:

#include <string>
#include <map>
#include <utility> // header for pair
#include <vector>

这种方法的缺点是预处理器每次都必须加载每个文件并通过#ifdef...#endif条件包含处理,所以如果你有数千个文件,每个文件中有几十个包含,这可能会显着增加你的编译时间. 然而,在大多数项目中,不得不手动管理头文件包含的额外恶化不值得编译时间的微小增益。这就是为什么 Scott Meyers 的Effective STL书将“始终#include the proper headers”作为第 48 项

于 2009-08-04T04:28:00.580 回答
5

#include <map>你的头文件中是否有某个地方?

把它放在那里至少看看它是否有效。无论如何,你应该这样做。

于 2009-08-04T04:11:23.710 回答
5

您应该将其中一些包含转移到您的头文件中。这些需要放在 typedef 语句之前。

IE

#include <map>
#include <string>
#include <map>

否则,包括 some_file.h 在内的任何其他内容(例如您的主程序)都不会知道它们是什么,除非它还将这些包含放在您的主程序源文件中的 #include "some_file.h" 包含指令之前。如果你这样做,问题应该会消失。

于 2009-08-04T04:16:26.307 回答
0

正如一些人指出的那样,编译器没有找到 map 的定义。由于您似乎包含地图标题,因此我可以想到其他两个可能的原因:

  1. 正在加载另一个名为 map 的头文件,而不是 std map 头。我认为这不太可能。
  2. 另一个标题是#define'ing map 是别的东西。

检查两者的一种方法是让您的编译器生成后处理文件,即在通过 C 预处理器运行但在编译之前的源文件。然后,您应该能够找到您的违规行,并查看地图类型是否已被其他内容替换。您还应该能够搜索备份文件并查看#include 被拉入的标题。

生成后处理文件的方式取决于编译器 - 检查文档中的 cmd-line 标志以了解您的编译器。

于 2009-08-04T05:54:10.897 回答