SFINAE -- basis: array of void is invalid type

B

Barry

The problem brought by one earlier post from comp.lang.c++
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/bf636c48b84957b/

I take part of the question and reproduce the code to represent (partly)
the question.

#include <iostream>

template <class>
void f(...)
{
std::cout << "..." << std::endl;
}

template <class T>
void f(T[1])
{
std::cout << "T" << std::endl;
}

int main()
{
f<int>(0);
f<void>(0);
}


as "array of void" is invalid type, so the f<void> should applies SFINAE
and chooses the "f(...)" version

the code above compiles and runs _expectedly_ with VC8
but fails to compile with Comuea Online, producing the error message:

"ComeauTest.c", line 10: error: array of void is not allowed
void f(T[1])
^
detected during instantiation of "f" based on template argument
<void> at line 18

compiles with gcc 4.3.0 but produced unexpected result, producing
T
T
which means that f<int>, f<void> both chooses the second version.

so who's right about this?

one more question:
should

8.3.5.3 [...] The type of a function is determined using the
following rules. The type of each parameter is determined from its own
decl-specifier-seq and declarator. After determining the type of each
parameter, 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.
[...]

the adjustment apply before SFINAE happens?
I guess GCC4.3.0 gives an "yes" answer.
 
C

courpron

The problem brought by one earlier post from comp.lang.c++http://groups.google.com/group/comp.lang.c++/browse_thread/thread/bf6...

I take part of the question and reproduce the code to represent (partly)
the question.

#include <iostream>

template <class>
void f(...)
{
   std::cout << "..." << std::endl;

}

template <class T>
void f(T[1])
{
   std::cout << "T" << std::endl;

}

int main()
{
   f<int>(0);
   f<void>(0);

}

as "array of void" is invalid type, so the f<void> should applies SFINAE
and chooses the "f(...)" version

the code above compiles and runs _expectedly_ with VC8
but fails to compile with Comuea Online, producing the error message:

"ComeauTest.c", line 10: error: array of void is not allowed
   void f(T[1])
           ^
           detected during instantiation of "f" based on template argument
                     <void> at line 18

compiles with gcc 4.3.0 but produced unexpected result, producing
T
T
which means that f<int>, f<void> both chooses the second version.

so who's right about this?

I guess VC8 is right.

SFINAE comes when type deduction fails, which can happen in the
following context :

14.8.2.2 :

"When an explicit template argument list is specified, the template
arguments must be compatible with the template parameter list and must
result in a valid function type as described below; otherwise type
deduction fails. Specifically, [...] Type deduction may fail for the
following reasons:
— Attempting to create an array with an element type that is void"
one more question:
should

8.3.5.3 [...] The type of a function is determined using the
following rules. The type of each parameter is determined from its own
decl-specifier-seq and declarator. After determining the type of each
parameter, 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.
[...]

the adjustment apply before SFINAE happens?
I guess GCC4.3.0 gives an "yes" answer.


Such adjustement is applied after SFINAE.

14.8.2.3 :

"After this substitution is performed, the function parameter type
adjustments described in 8.3.5 are performed."

Alexandre Courpron.
 
F

Fei Liu

The problem brought by one earlier post from comp.lang.c++http://groups.google.com/group/comp.lang.c++/browse_thread/thread/bf6...

I take part of the question and reproduce the code to represent (partly)
the question.

#include <iostream>

template <class>
void f(...)
{
std::cout << "..." << std::endl;

}

template <class T>
void f(T[1])
{
std::cout << "T" << std::endl;

}

int main()
{
f<int>(0);
f<void>(0);

}

as "array of void" is invalid type, so the f<void> should applies SFINAE
and chooses the "f(...)" version

the code above compiles and runs _expectedly_ with VC8
but fails to compile with Comuea Online, producing the error message:

"ComeauTest.c", line 10: error: array of void is not allowed
void f(T[1])
^
detected during instantiation of "f" based on template argument
<void> at line 18

compiles with gcc 4.3.0 but produced unexpected result, producing
T
T
which means that f<int>, f<void> both chooses the second version.

so who's right about this?

I guess VC8 is right.

SFINAE comes when type deduction fails, which can happen in the
following context :

14.8.2.2 :

"When an explicit template argument list is specified, the template
arguments must be compatible with the template parameter list and must
result in a valid function type as described below; otherwise type
deduction fails. Specifically, [...] Type deduction may fail for the
following reasons:
— Attempting to create an array with an element type that is void"
one more question:
should

8.3.5.3 [...] The type of a function is determined using the
following rules. The type of each parameter is determined from its own
decl-specifier-seq and declarator. After determining the type of each
parameter, 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.
[...]

the adjustment apply before SFINAE happens?
I guess GCC4.3.0 gives an "yes" answer.


Such adjustement is applied after SFINAE.

14.8.2.3 :

"After this substitution is performed, the function parameter type
adjustments described in 8.3.5 are performed."

Alexandre Courpron.

This suggests that VC8 is probably doing the correct thing. First SFINAE
kicks in and the ... version is chosen, then void[1] decays to void *
and becomes a valid type.

Although now I could understand why comeau is reporting an error, not
taking into account the decay effect, void[1] is an invalid type
regardless. But in the same vein, it's still doing something wrong when
it takes void(*)[1] without reporting any error.

SFINAE needs to be better standardized and documented. Intel compiler
behaves exactly like comeau, different from g++ and vc8.

Fei
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top