我写的一些代码有一个非常讨厌的问题。我发现其他人在stackoverflow上有同样的问题,我尝试了解决方案,但没有一个对我有效。
我输入了几个我正在使用的常见STL类型,除了我尝试输入一个地图之外没有任何问题。 我得到一个“some_file.h:83:错误:在'<'之前的预期初始化程序令牌“在测试程序中包含我的标题时出错。
这是标题的重要部分(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"
测试文件只包含该顺序的字符串,矢量和我的文件。它有一个主要的方法,只是做一个hello world的事情。
有趣的是,我很快就将一个模板化的课程拼凑在一起,看看问题出在哪里(用“std::map<Column...
”替换“hello<Column...
”)并且它没有问题。
如果您使用的是没有“<
”运算符的类,我已经创建了地图所需的运算符重载。
答案 0 :(得分:14)
您遇到此问题是因为编译器不知道地图是什么。它不知道,因为尚未包括地图标题。您的标题使用STL模板:字符串,矢量,地图和&amp;对。但是,它没有定义它们,也没有任何参考它们的定义。您的测试文件barfs在地图上而不是在字符串或向量上的原因是您在some_file.h之前包含字符串和向量标题,因此定义了字符串和向量,但是映射不是。如果你包含map的标题,它会起作用,但是它可能会抱怨pair(除非你的特定STL实现在map的标题中包含了对)。
通常,最好的策略是为您在自己的标头中使用的每种类型添加适当的标准标头。所以some_file.h至少应该有这些标题:
#include <string>
#include <map>
#include <utility> // header for pair
#include <vector>
这种方法的缺点是预处理器每次都必须加载每个文件并完成#ifdef
... #endif
条件包含处理,所以如果你有数千个文件,那么几十个在每个文件中包含,这可能会显着增加您的编译时间。但是,在大多数项目中,必须手动管理标头包含的额外加重并不值得在编译时获得微不足道的收益。
这就是为什么斯科特迈耶斯的书Effective STL将“总是#include正确的标题”作为item #48。
答案 1 :(得分:5)
头文件中是否有#include <map>
?
把它放在那里至少看它是否有效。无论如何你应该这样做。
答案 2 :(得分:5)
您应该将其中一些包含转移到头文件中。这些需要放在你的typedef语句之前。
即
#include <map>
#include <string>
#include <map>
否则,包括some_file.h在内的任何其他内容(例如您的主程序)都不会知道它们是什么,除非它还在主程序源文件中的#include“some_file.h”include指令之前放置这些包含。如果你这样做,问题就会消失。
答案 3 :(得分:0)
正如几位人士指出的那样,编译器没有找到map的定义。由于您似乎包含地图标题,因此我可以想到另外两个可能的原因:
检查其中一种方法是让编译器生成后处理文件,即源文件在通过C预处理器运行之后但在编译之前。然后,您应该能够找到您的违规行,并查看地图类型是否已被其他内容替换。您还应该能够搜索该文件,并查看#include所选的标题。
如何生成后处理文件取决于编译器 - 检查编译器文档中的cmd-line标志。