2009-08-04 3 views
3

У меня очень неприятная проблема с кодом, который я написал. Я нашел кого-то другого, у которого была такая же проблема в stackoverflow, и я попробовал решения, но никто не работал для меня.C++ STL map typedef ошибки

Я набрал несколько обычных типов STL, которые я использую, и ни у кого из других проблем нет, кроме как при попытке набрать карту. Я получаю сообщение «some_file.h: 83: error: expected initializer before» < «токен» при включении моего заголовка в тестовую программу.

Вот важная часть заголовка (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" 

Тестовый файл просто включает строку, вектор, и мой файл в этом порядке. У этого есть основной метод, который только приветствует мир.

Самое смешное, что я быстро собрал шаблонный класс, чтобы увидеть, где проблема (заменив «std::map<Column...» на «hello<Column...»), и это сработало без проблем.

Я уже создал перегрузку оператора, требуемую картой, если вы используете класс без оператора '<'.

+0

Какое сообщение об ошибке вы получили? –

+2

Я бы сказал, что это хороший пример злоупотребления 'typedef'. –

+1

И я бы сказал, что намного проще выписать col_vec вместо std :: vector . То же самое касается итератора, col_vec_i означает для меня гораздо больше, чем std :: vector :: iterator. Это может быть «жестокое обращение», но это облегчает мне жизнь. – user150113

ответ

14

Вы получаете эту проблему, потому что компилятор не знает, что такое карта. Он не знает, потому что заголовок карты еще не включен. В вашем заголовке используются шаблоны STL: строка, вектор, карта, &. Однако он не определяет их или не ссылается на то, где они определены. Причина, по которой ваш тестовый файл barfs на карте, а не на строке или векторе, заключается в том, что вы включаете заголовки строк и векторов перед some_file.h, поэтому строка и вектор определены, но карта не является. Если вы включите заголовок карты, он будет работать, но тогда он может жаловаться на пару (если ваша конкретная реализация STL не включает пару в заголовок карты).

Как правило, лучшей политикой является включение правильного стандартного заголовка для каждого типа, который вы используете в своем собственном заголовке. Так some_file.h должны иметь, по крайней мере, эти заголовки:

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

Недостатком этого подхода является то, что препроцессор должен загрузить каждый файл каждый раз, и пройти через условную обработку включения в #ifdef ... #endif, так если у вас есть тысячи файлов и десятки включений в каждом файле, это может значительно увеличить время компиляции.Однако, по большинству проектов, добавленное обострение необходимости управления включением заголовка вручную не стоит минимального выигрыша во время компиляции. Вот почему книга Скотта Мейерса «Effective STL» имеет «Всегда # включать правильные заголовки», как item #48.

+0

Facepalm! Обычно я включаю STL-файл в программу, а не заголовок. Спасибо за ссылку. – user150113

+0

Теперь я знаю, что я * должен * включать в заголовок STL-материал. – user150113

+1

Чтобы ускорить компиляцию в большом проекте, включите только put, которые относятся к этому файлу заголовка. Соответствующий исходный файл должен включать только заголовочный файл и любые дополнительные файлы, относящиеся к исходной реализации. – Matt

5

Есть ли #include <map> где-то в вашем файле заголовка?

Поместите это там, чтобы хотя бы посмотреть, работает ли оно. Вы все равно должны это делать.

5

Вы должны перенести некоторые из этих включений в файл заголовка. Они должны быть размещены перед вашими заявлениями typedef.

т.е.

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

В противном случае, все остальное, включая some_file.h (например, основной программы) не будут знать, что они, если он также не помещает их включает в себя перед #include «some_file.h» включают в себя директивы в исходном файле основной программы. Если вы это сделаете, проблема должна исчезнуть.

+0

Ничего себе, не могу поверить, что я пропустил это! В любом случае, я обычно включаю все материалы STL в основную программу, чтобы эта проблема не возникала. Спасибо, что указали это. – user150113

0

Как указало несколько человек, компилятор не находит определение для карты. Поскольку вы, кажется, включаете заголовок карты, есть две другие возможные причины, которые я могу придумать:

  1. Другой заголовочный файл, называемый map, загружается вместо заголовка std. Я думаю, что это маловероятно.
  2. Другим заголовком является # define'ing map, чтобы быть чем-то другим.

Один из способов проверить, является ли ваш компилятор для создания пост-обработанного файла, то есть исходного файла после его запуска через предварительный процессор C, но до его компиляции. Затем вы сможете найти свою оскорбительную линию и посмотреть, был ли тип карты заменен чем-то другим. Вы также должны иметь возможность искать резервную копию файла и видеть, какой заголовок включен в #include.

Как вы создаете файл после обработки, зависит от компилятора - проверьте флаги cmd-строки в документах для вашего компилятора.

+0

Для gcc: используйте gcc -E для просмотра постобработочного файла. – quark

Смежные вопросы