我写的一些代码遇到了一个非常棘手的问题。我发现其他人在 stackoverflow 上遇到了同样的问题,我尝试了解决方案,但没有一个对我有用。
我对我正在使用的几个常见的 STL 类型进行了类型定义,其他的都没有任何问题,除非我尝试对 map 进行类型定义。 在测试程序中包含我的 header 时,出现“some_file.h:83: error: expected initializer before '<' token”错误。
这是 header (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"
测试文件仅按顺序包含字符串、 vector 和我的文件。它有一个 main 方法,只做 hello world 之类的事情。
有趣的是,我很快拼凑了一个模板类来查看问题出在哪里(将“std::map<Column...
”替换为“hello<Column...
”)并且它没有问题。
如果您使用的类没有' <
,我已经创建了映射所需的运算符重载' 运算符(operator)。
最佳答案
你遇到这个问题是因为编译器不知道什么是 map 。它不知道,因为尚未包含 map header 。您的 header 使用 STL 模板:字符串、 vector 、映射和对。但是,它没有定义它们,也没有引用它们的定义位置。您的测试文件 barfs 在 map 而不是 string 或 vector 上的原因是您在 some_file.h 之前包含了 string 和 vector header ,因此定义了 string 和 vector,但 map 没有。如果您包含 map 的 header ,它会工作,但它可能会提示对(除非您的特定 STL 实现在 map 的 header 中包含对)。
通常,最好的策略是为您在自己的 header 中使用的每种类型包含适当的标准 header 。所以 some_file.h 至少应该有这些标题:
#include <string>
#include <map>
#include <utility> // header for pair
#include <vector>
这种方法的缺点是预处理器每次都必须加载每个文件并经过#ifdef
... #endif
条件包含处理,所以如果您有数千个文件,每个文件中包含数十个,这可能会显着增加编译时间。然而,在大多数项目中,必须手动管理 header 包含所带来的额外麻烦并不值得在编译时间上获得微不足道的 yield 。
这就是为什么 Scott Meyers 的 Effective STL这本书有“总是 #include 正确的标题”作为 item #48 .
关于C++ STL 映射类型定义错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1225695/