SFINAE -- basis: array of void is invalid type

Discussion in 'C++' started by Barry, May 29, 2008.

  1. Barry

    Barry Guest

    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.


    --
    Best Regards
    Barry
     
    Barry, May 29, 2008
    #1
    1. Advertising

  2. Barry

    Guest

    On 29 mai, 08:36, Barry <> wrote:
    > 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.
     
    , May 29, 2008
    #2
    1. Advertising

  3. Barry

    Fei Liu Guest

    wrote:
    > On 29 mai, 08:36, Barry <> wrote:
    >> 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
     
    Fei Liu, May 29, 2008
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ollej Reemt
    Replies:
    7
    Views:
    580
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    828
    The Real OS/2 Guy
    Oct 28, 2003
  3. Replies:
    5
    Views:
    863
    S.Tobias
    Jul 22, 2005
  4. Replies:
    1
    Views:
    428
    Victor Bazarov
    May 23, 2007
  5. Replies:
    14
    Views:
    557
    bijeshn
    Apr 8, 2008
Loading...

Share This Page