f



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

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! ]

0
litb
5/4/2009 12:07:14 PM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8509) is leader. Post Follow

3 Replies
785 Views

Similar Articles

[PageSpeed] 28

>
> 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 ;-)


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

0
gneppert
5/5/2009 1:49:07 PM
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

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

0
SG
5/5/2009 1:51:04 PM
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


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

0
Seungbeom
5/6/2009 7:39:38 AM
Reply: