следующие работы в msvc2008 и MSVC2010 только что мелкие:Может ли встроенная функция вызова C++ объявлена позже в заголовке?
class Foo {
public:
static void FuncA(void) {
FuncB(); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(void);
};
Да, это своего рода странно: FuncA()
звонки FuncB()
, даже если (на тот момент) FuncB()
не-еще-заявлены. Однако MSVC2008 и MSVC2010 считают, что это нормально.
По-видимому, gcc
не думаю, что это прекрасно - FuncB was not declared in this scope
.
ВОПРОС: У меня их куча, и было бы «болью» объявить их, а затем определить их. Кроме того, было бы трудно «упорядочить» их должным образом, чтобы каждый из них только вызывал функции после того, как они были объявлены. Но, я предполагаю, что мне нужно объявить сначала-то-определить-позже?
Существуют ли разные правила, являются ли эти функции шаблонами или нет или определены в классе шаблонов или нет?
В частности, я заметил, что Microsoft очень «скомпонована», когда она принимает тонны взаимосвязанного кода, а LATER разрешает (при компиляции, когда запускается шаблонная параметризация), в то время как gcc
, похоже, хочет compile сейчас, когда он «видит» код (начальный проход для правильности, и снова во время параметризации/вызова).
(Эта проблема показывает, как мы порта наш код Microsoft для Linux/GCC.)
=== UPDATE ===
Ниже приведены "альтернативные" сценарии, которые мы имеем (в это усиление кода), и будет ли ваш ответ изменяться на основе любого из них?
// Alternate-Scenario-B
class Foo2 {
public:
template<typename SOME_TYPE>
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
template<typename SOME_TYPE>
static void FuncB(const SOME_TYPE& some_type);
};
... и:
// Alternate-Scenario-C
template<typename SOME_TYPE>
class Foo3 {
public:
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(const SOME_TYPE& some_type);
};
=== UPDATE + 2 ===
Спасибо за комментарии, где консенсус, кажется, что это справедливо C++ код, и должен работать (как предлагалось @Adam, функция «defined-inline» должна вести себя так, как если бы она была определена после класса, и должна иметь возможность вызывать функции, определенные в интерфейсе класса после этого встроенного определения).
Дополнительная информация:
Да, у меня действительно есть эта ошибка компиляции из первого примера в реализации FuncA()
инлайн:
'FuncB' is not a member of 'Foo'
... с помощью:
gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
(Напомним, что это работает на MSVC2008/MSVC2010).
теперь я понимаю, что мой код-пример (выше) является недостаточным (в приведенном выше примере не показывает эту ошибку на gcc
), вот еще некоторые детали:
Foo
имеет базовый класс (I не думаю, что должно волновать)Foo
определяет внутреннююenum
который проходит через эти funcs (я не думаю, что это имеет значение)- эти функции «расширенные» через макрос (я думаю, что значительное - см ниже)
- есть пятьдесят-шесть (56) из этих функций (я думаю, что значительное - см ниже)
Более полный пример кода будет (и я не горжусь этим):
#define FOO_FUNCS(CLASS_NAME,CLASS_ENUM) \
static void FuncA(CLASS_ENUM value_enum) { \
FuncB(value_enum); /*PROBLEM*/ \
} \
static void FuncB(CLASS_ENUM value_enum) { \
FuncC(value_enum); \
} \
/*...THERE ARE 56 FUNCS IN THIS MACRO, THREE LINES EACH...*/
class Foo : public FooParent {
public:
enum FooEnum { FOO_ONE, FOO_TWO };
FOO_FUNCS(Foo,FooEnum) // EXPAND THE 56 FUNCS
};
КОД НАМЕРЕНИЯ: Базовый класс FooParent
имеет реализацию, предназначенную для «совместного использования» (многими) производными классами. Производные классы определяют свои собственные значения enum
. Функции, которые использовали эти значения enum
, были реализованы с помощью макроса (поскольку FooParent
не является template<>
и не может полагаться на полученный enum
).
Любопытный поведение:
- Если
FooA(){FooB();}
вложенности ссылок функция, определенная «позже» лишь на «несколько линий», тоgcc
отлично компилируется. Однако, если еще не объявленная функция намного позже, напримерFoo2(){Foo53();}
, тоgcc
делает вывод, чтоFoo53()
не является членом класса (но это так).
Вот что я думаю, что происходит:
- Там, кажется, проблема с большим-оф-кода (для 56 функций), которые физически на «одной линии». Если я выберу эти функции из макроса, И, если я удалю
\
escape-line-endings, тоgcc
компилируется в порядке.
Таким образом, я думаю, что (код-портирование) Ответ:
- не использовать препроцессор-макро
- сделать класс
FooParentBase<>
шаблон, полученный изFooParent
, из которого мы выводимFoo
, которая требуетtypename Foo::enum
в качестве шаблона-параметра
Я в порядке с этими изменениями (я не люблю макрос), но я нахожу это странным, что gcc
, похоже, проблема.
Есть ли другие рекомендации, как это исправить? (Является ли вышеупомянутый перерасчет того, что вы бы сделали?)
В вашем вопросе упоминаются шаблоны, но кода их нет. Возможно, вам нужен второй пример кода? –
@Ben, спасибо, обновленный вопрос с примером 'template <>', но теперь я не думаю, что шаблоны являются частью проблемы (см. «UPDATE + 2») – charley