From: Joshua Lehrer on
I contend that the following code should not compile. However, on
various compilers with varying versions of the EDG front end, it
either crashes the compiler, compiles. or fails to compile.

Am I correct that this code is ill-formed?

template <typename F>
inline void call(F func) { func(); }

void routine(int i=3);

int main() {
call(&routine);
}

void routine(int i) { }

-J

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 16 Jul., 18:20, Joshua Lehrer <usenet_...(a)lehrerfamily.com> wrote:
> I contend that the following code should not compile. However, on
> various compilers with varying versions of the EDG front end, it
> either crashes the compiler, compiles. or fails to compile.
>
> Am I correct that this code is ill-formed?
>
> template <typename F>
> inline void call(F func) { func(); }
>
> void routine(int i=3);
>
> int main() {
> call(&routine);
>
> }
>
> void routine(int i) { }

The code is ill-formed, because function default arguments
apply only to the concretely named function, not to a
pointer to a function. Even, if the explicit address operator
is removed, the compiler will deduce template paramteer F to
void(*)(int) which means that a function call expression via
this pointer must get an argument convertible to int.

According to 8.3.5/4 in the C++03 standard:

"[..] The return type, the parameter type list and the cv-
qualifier-seq, but not the default arguments (8.3.6) or the
exception specification (15.4), are part of the function
type. [Note: function types are checked during the assignments
and initializations of pointer-to-functions, reference-to-
functions, and pointer-to-member-functions. ] [..]"

8.3.6/9 emphasizes this by normative wording:

"[..] A default argument is not part of the type of a function.
[Example:
int f(int = 0);
void h() {
int j = f(1);
int k = f(); // OK, means f(0)
}
int (*p1)(int) = &f;
int (*p2)() = &f; // error: type mismatch
[..]"

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Magnus Müller on
On Fri, 16 Jul 2010 10:20:01 CST
Joshua Lehrer <usenet_cpp(a)lehrerfamily.com> wrote:

::I contend that the following code should not compile. However, on
::various compilers with varying versions of the EDG front end, it
::either crashes the compiler, compiles. or fails to compile.
::
::Am I correct that this code is ill-formed?
::
::template <typename F>
::inline void call(F func) { func(); }
::
::void routine(int i=3);
::
::int main() {
:: call(&routine);
::}
::
::void routine(int i) { }

Based on my understanding, I consider this code illformed, as the signature of the function routine is void (*) (int). For the upper code to work, func should be deducted to void (*) (). Therefore, the call func () can't work.
g++ behaves in this way:

% make illformed
g++ illformed.cc -o illformed
illformed.cc: In function 'void call(F) [with F = void (*)(int)]':
illformed.cc:10: instantiated from here
illformed.cc:4: error: too few arguments to function

So, g++ thinks this function is meant to have a parameter and doesn't care about the default argument. I guess other compilers should handle this issue in the same way.


Regards, mm


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]