Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SFINAE with invalid function-type or array-type parameters?

45 views
Skip to first unread message

litb

unread,
May 4, 2009, 3:07:14 PM5/4/09
to
Please consider this code:

// snip
template<typename T>
char (&f(T[1]))[1];

template<typename T>
char (&f(...))[2];

int main() { char c[sizeof(f<void()>(0)) == 2]; }
// snap

I expected it doing SFINAE and chosing the second overload, since
substitution of T into T[1] yields

void [1]()

Which is an invalid type, of course. Adjustment of parameter types
(array->pointer) is done after substituting template parameters into
function parameters and checking for valid resulting types like 14.8.2
[temp.deduct] describes.

But both comeau and GCC fail to compile the above. Both with different
diagnostics:

// snip
Comeau says:

"ComeauTest.c", line 2: error: array of functions is not allowed
char (&f(T[1]))[1];


GCC says:

error: ISO C++ forbids zero-size array 'c'
// snap

Who is right and is my code valid at all?

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

gnep...@web.de

unread,
May 5, 2009, 4:49:07 PM5/5/09
to

>
> int main() { char c[sizeof(f<void()>(0)) == 2]; }
> // snap
>
> I expected it doing SFINAE and chosing the second overload, since
> substitution of T into T[1] yields
>
> void [1]()
>
> Which is an invalid type, of course.

Agreed. Thus, the only valid candiate in the overload set should be
the vararg function template.

> Comeau says:
>
> "ComeauTest.c", line 2: error: array of functions is not allowed
> char (&f(T[1]))[1];
>

Seems to be a parser error.

> GCC says:
>
> error: ISO C++ forbids zero-size array 'c'
> // snap

Seems to pick the first (non-vararg) function template.


> Who is right and is my code valid at all?
>

My 2 cents: neither. Your code should be correct, albeit thoroughly
obfuscated ;-)

SG

unread,
May 5, 2009, 4:51:04 PM5/5/09
to
On 4 Mai, 21:07, litb <Schaub-Johan...@web.de> wrote:
>
> template<typename T>
> char (&f(T[1]))[1];
>
> template<typename T>
> char (&f(...))[2];
>
> int main() { char c[sizeof(f<void()>(0)) == 2]; }
> // snap
>
> I expected it doing SFINAE and chosing the second overload, since
> substitution of T into T[1] yields
>
> void [1]()
>
> Which is an invalid type, of course.

My initial thought was that this should work as a function's parameter
type because

void foo(int x[1]);

is no different from

void foo(int* x);

By that logic void x[1]() would be equivalent to void(*x)() in this
context. But I could not compile the following snippet

void foo(void x[1]());

using G++ 4.3.2. It says: "error: declaration of 'x' as array of
functions". Strangely enough it works as a template

template<typename T>
void foo(T x[1]) {}

int main() {
foo<void()>(0); // compiles fine
}


Cheers!
SG

Seungbeom Kim

unread,
May 6, 2009, 10:39:38 AM5/6/09
to
SG wrote:
>
> My initial thought was that this should work as a function's parameter
> type because
>
> void foo(int x[1]);
>
> is no different from
>
> void foo(int* x);
>
> By that logic void x[1]() would be equivalent to void(*x)() in this
> context.

This is interesting. 8.3.5/3 says:

> [..] any parameter of type "array of T" or "function returning T" is
> adjusted to be "pointer to T" or "pointer to function returning T,"
> respectively.

but 8.3.5/6 also says:

> There shall be no arrays of functions, although there can be arrays
> of pointers to functions.

So it would depend on which rule gets applied first.
I cannot figure out whether it's well-formed or not.

--
Seungbeom Kim

0 new messages