我几乎所有东西都使用typedef,包括函数。在过去的几周里,我一直在调整我们的C ++代码,以尽可能完全符合ISO C ++ 11标准,使用最终草案文档(N3242)作为指南。
正如我们所知,偶尔会有多个声明通过出现在多个文件中的externs或者重复的typedef进入我们的代码。根据上述doco的第7.1.3节,第145页的摘录,这应该是无害的:
3。在给定的非类作用域中,可以使用typedef说明符重新定义该作用域中声明的任何类型的名称,以引用它已引用的类型。
[例如:
typedef struct s { /* ... */ } s; typedef int I; typedef int I; typedef I I;
- 结束示例]
所以,我写了一个程序来测试这个。最简单的形式:
typedef int (fcntype)(int, int);
extern fcntype fcn1;
int fcn1(int x, int y) { return x + y; }
int main(int argc, char ** argv) { return fcn1(2, 3); }
使用gcc编译
-Wfatal-errors -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -c -Wstrict-null-sentinel -std=c++0x -pedantic -Wall -Wextra
当然没有问题。让我们复制函数decl:
typedef int (fcntype)(int, int);
extern fcntype fcn1;
extern fcntype fcn1; // woops. probably from an #include ...
int fcn1(int x, int y) { return x + y; }
int main(int argc, char ** argv) { return fcn1(2, 3); }
正如标准预测的那样,没有问题。让我们对原作做出不同的改变:
typedef int (fcntype)(int, int=0); // default param.
extern fcntype fcn1;
int fcn1(int x, int y) { return x + y; }
int main(int argc, char ** argv) { return fcn1(2); } // use the default param
再次,没有问题。当我们同时具有重复的decl和默认参数时会出现问题:
typedef int (fcntype)(int, int=0); // default param.
extern fcntype fcn1;
extern fcntype fcn1; // FYI this is line 3 in the error message below.
int fcn1(int x, int y) { return x + y; }
int main(int argc, char ** argv) { return fcn1(2); } // use the default param
gcc抱怨
decltest.cpp:3: error: default argument given for parameter 2 of ‘int fcn1(int, int)’
当然,我正在按照应该清理的方式清理代码,也就是说我将decls集中到一个更好组织的文件中。但这是编译器中的错误还是对我的默认参数“是”的误解?
答案 0 :(得分:6)
首先,对于具有相同类型的相同函数声明,最多只能有一个定义默认参数的声明。这是由于§8.3.6[dcl.fct.default] / 4:
...默认参数不能由后来的声明重新定义(甚至不是相同的值)。 [示例:
... void m() { void f(int, int); // has no defaults f(4); // error: wrong number of arguments void f(int, int = 5); // OK f(4); // OK, calls f(4, 5); void f(int, int = 5); // error: cannot redefine, even to same value } ...
- 结束示例] ...
另外,正如@Sven注意到的那样,默认参数不会出现在typedef
中,尽管即使使用-pedantic
g ++也无法捕获它。我认为clang和Visual C++拒绝这一点,但我没有尝试过。
答案 1 :(得分:1)
您的标准报价不适用于此处,因为您没有多次声明typedef,而是多次使用它。
默认参数确实是一个棘手的情况,它们只能出现在一个声明中(并且记住,定义本身算作一个声明,即使将默认参数放在前向声明和定义中都是错误的。)
答案 2 :(得分:0)
这会产生相同的错误:
extern int fcn1(int, int=0);
extern int fcn1(int, int=0);
因此,typedef
版本不起作用并不奇怪。