C ++ STL карта typedef ошибки - PullRequest
       28

C ++ STL карта typedef ошибки

3 голосов
/ 04 августа 2009

У меня действительно неприятная проблема с кодом, который я написал. Я нашел кого-то еще, у кого была та же проблема со стековым потоком, и я попробовал решения, но ни один не работал для меня.

Я печатаю определения нескольких распространенных типов STL, которые я использую, и ни у одного из других нет проблем, кроме случаев, когда я пытаюсь определить карту. При включении моего заголовка в тестовую программу я получаю сообщение об ошибке "some_file.h: 83: error: ожидаемый инициализатор перед знаком '<' token". </p>

Вот важная часть заголовка (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...»), и она работала без проблем.

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

Ответы [ 4 ]

14 голосов
/ 04 августа 2009

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

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

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

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

5 голосов
/ 04 августа 2009

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

т.е.

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

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

5 голосов
/ 04 августа 2009

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

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

0 голосов
/ 04 августа 2009

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

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

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

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

...