Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ STL map typedef errors

I'm having a really nasty problem with some code that I've written. I found someone else that had the same problem on stackoverflow and I tried the solutions but none worked for me.

I typedef several common STL types that I'm using and none of the others have any problem except when I try to typedef a map. I get a "some_file.h:83: error: expected initializer before '<' token" error when including my header in a test program.

Here's the important part of the 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;

The includes in some_file.cpp are:

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

The test file simply includes string, vector, and my file in that order. It has a main method that just does a hello world sort of thing.

The funny thing is that I quickly threw together a templated class to see where the problem was (replacing the "std::map<Column..." with "hello<Column...") and it worked without a problem.

I've already created the operator overload required by the map if you're using a class without a '<' operator.

like image 336
user150113 Avatar asked Nov 29 '22 12:11

user150113


1 Answers

You are getting this problem because the compiler doesn't know what a map is. It doesn't know because the map header hasn't been included yet. Your header uses the STL templates: string, vector, map, & pair. However, it doesn't define them, or have any reference to where they are defined. The reason your test file barfs on map and not on string or vector is that you include the string and vector headers before some_file.h so string and vector are defined, but map is not. If you include map's header, it will work, but then it may complain about pair (unless your particular STL implementation includes pair in map's header).

Generally, the best policy is to include the proper standard header for every type you use in your own header. So some_file.h should have, at least, these headers:

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

The downside to this approach is that the preprocessor has to load each file every time and go through the #ifdef ... #endif conditional inclusion processing, so if you have thousands of files, and dozens of includes in each file, this could increase your compilation time significantly. However, on most projects, the added aggravation of having to manage the header inclusion manually is not worth the miniscule gain in compilation time. That is why Scott Meyers' Effective STL book has "Always #include the proper headers" as item #48.

like image 188
A. Levy Avatar answered Dec 09 '22 08:12

A. Levy