title: Multiple declarations of C++ functions with default parameters
body: <p>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.</p>
  <p>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:</p>
  <blockquote>
  <p>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.</p>
  <p>[ Example:</p>
  <pre><code>   typedef struct s { /* ... */ } s; 
     typedef int I; 
     typedef int I; 
     typedef I I;
  </code></pre>
  <p>— end example ]</p>
  </blockquote>
  <p>So, I wrote a program to test this. In its simplest form:</p>
  <pre><code>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); }
  </code></pre>
  <p>Compiling using gcc with</p>
  <pre><code> -Wfatal-errors -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -c -Wstrict-null-sentinel -std=c++0x -pedantic -Wall -Wextra
  </code></pre>
  <p>there are, of course, no problems. Let's dup the function decl:</p>
  <pre><code>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); }
  </code></pre>
  <p>As the standard predicts, no problems. Let's make a different change to the original:</p>
  <pre><code>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
  </code></pre>
  <p>Again, no problems. The problem comes about when we have both the duplicate decl and the defaulted parameter like this:</p>
  <pre><code>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
  </code></pre>
  <p>And gcc complains with</p>
  <pre><code>decltest.cpp:3: error: default argument given for parameter 2 of ‘int fcn1(int, int)’
  </code></pre>
  <p>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 &quot;is&quot;?</p>