以下在 MSVC2008 和 MSVC2010 中运行良好:
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
。
ISSUE: 我有一堆这些,声明它们然后定义它们会很“痛苦”。此外,很难正确地“排序”它们,因此每个函数都只在声明后调用函数。 但是,我猜我需要先声明,然后再定义?
这些函数是不是模板,还是在模板类中定义的规则是否不同?
具体来说,我注意到微软非常“后期编译”,它接受大量相互耦合的代码,并且稍后解析(在编译时,当模板参数化被触发时),而现在gcc
似乎想要编译它“看到”代码(正确性的初始传递,并在参数化/调用期间再次传递)。
(当我们将 Microsoft 代码移植到 Linux/gcc 时,就会出现这个问题。)
===更新===
以下是我们拥有的“替代”场景(在此代码移植工作中),您的答案会根据其中任何一个而改变吗?
// 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);
};
===更新+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
有一个基类(我认为这不重要)Foo
定义一个通过这些函数传递的内部enum
(我认为这不重要)- 这些功能通过宏“扩展”(我认为很重要——见下文)
- 这些功能中有五十六 (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
不是 a template<>
,并且不能依赖于派生的enum
- )。
奇怪的行为:
- 如果
FooA(){FooB();}
嵌套仅通过“几行”引用“稍后”定义的函数,则gcc
可以正常编译。但是,如果尚未声明的函数要晚得多,例如Foo2(){Foo53();}
,则gcc
断定它Foo53()
不是类的成员(但它是)。
这是我认为正在发生的事情:
- 物理上位于“单行”上的大量代码(用于 56 个函数)似乎存在问题。如果我将这些函数从宏中取出,并且如果我删除了
\
转义行结尾,那么gcc
编译得很好。
因此,我认为(代码移植)答案是:
- 不要使用预处理器宏
- 制作一个
FooParentBase<>
派生自 的模板类FooParent
,我们从中派生Foo
,这需要typename Foo::enum
作为模板参数
我对这些更改很好(我不喜欢宏),但我觉得这里gcc
似乎有问题很奇怪。
对于如何解决这个问题还有其他建议吗?(上面是否重新考虑了你会做什么?)