I use typedefs for almost everything, including functions. Over the past few weeks, I have been tarting up our C++ code to conform as exactly as possible to the ISO C++11 standard, using the final draft document (N3242) as a guide.
As we know, there are occasional multiple declarations that creep into our code through externs appearing in more than one file, or typedefs that are repeated. According to this excerpt from section 7.1.3, page 145 of the above doco, this should be harmless:
3. In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.
[ Example:
typedef struct s { /* ... */ } s; typedef int I; typedef int I; typedef I I;
— end example ]
So, I wrote a program to test this. In its simplest form:
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); }
Compiling using gcc with
-Wfatal-errors -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -c -Wstrict-null-sentinel -std=c++0x -pedantic -Wall -Wextra
there are, of course, no problems. Let's dup the function 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); }
As the standard predicts, no problems. Let's make a different change to the original:
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
Again, no problems. The problem comes about when we have both the duplicate decl and the defaulted parameter like this:
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
And gcc complains with
decltest.cpp:3: error: default argument given for parameter 2 of ‘int fcn1(int, int)’
Of course, I am cleaning up the code the way it should be cleaned up, which is to say I am corralling the decls into one, better organized file. But is this a bug in the compiler or a misunderstanding of mine about what a default parameter "is"?
Firstly, for the same function declaration with same types, there should only be at most one declaration which define the default arguments. This is due to §8.3.6 [dcl.fct.default]/4:
... A default argument shall not be redefined by a later declaration (not even to the same value). [ Example:
... 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 } ...
— end example ] ...
Also, as @Sven noticed, a default argument shall not appear in a typedef
, although g++ cannot catch it even with -pedantic
. I think clang and Visual C++ reject this but I haven't tried.
Your standard quote doesn't apply here, since you're not declaring the typedef multiple times, but using it multiple times.
Default arguments are indeed a tricky case, they can only appear in one declaration (and remember, the definition itself counts as a declaration, even putting the default argument in both a forward declaration and a definition is an error).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With