• cv-qualified function type and type deduction

    From wander@21:1/5 to All on Sat Feb 20 07:15:53 2016
    Good day!
    I came across an interesting feature in the behavior of popular
    compilers and would like to understand the reasons.
    There's a simple code:

    #include <iostream>

    template <typename F>
    void (* declval() ) (F);

    template <typename X>
    char (& probe( void(*) ( X * ) ) )[1];

    template <typename X>
    char (& probe( void(*) ( X ) ) )[2];

    int main()
    {
    std::cout << sizeof( probe(declval<void() const>()) );
    }

    The question is about type deduction. If you run this code on
    * compiler GCC 4.8.x (or later)
    * compiler Clang 3.4 (or later)
    * compiler in the Visual Stuido (tested on VS 2013 Community)
    * compiler Intel ICC 13.0.1

    it will display the number "1". And I thought it is logical, since
    function type, being substituted argument in another function, acquires
    the properties of a pointer type.
    On newer versions of compilers mentioned (except for VS and ICC)
    behavior has changed and now this code for Clang 3.5 (or higher), GCC
    4.9 (or higher) displays the number "2". If you remove the second
    overload, then the mentioned versions of GCC and Clang error occurs:
    "Forming pointer to qualified function type"
    I understand why but doubt whether this rule applies in this context.

    In particular, it would be interesting to know whether the behavior of
    the new and old versions of the compilers conforms to C++ Standard.

    Maybe together we can find the truth.
    Thank you.


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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Daniel_Kr=c3=bcgler?=@21:1/5 to All on Mon Feb 22 19:49:40 2016
    Am 20.02.2016 um 14:15 schrieb wander:

    Good day!
    I came across an interesting feature in the behavior of popular
    compilers and would like to understand the reasons.
    There's a simple code:

    #include <iostream>

    template <typename F>
    void (* declval() ) (F);

    template <typename X>
    char (& probe( void(*) ( X * ) ) )[1];

    template <typename X>
    char (& probe( void(*) ( X ) ) )[2];

    int main()
    {
    std::cout << sizeof( probe(declval<void() const>()) );
    }

    The question is about type deduction. If you run this code on
    * compiler GCC 4.8.x (or later)
    * compiler Clang 3.4 (or later)
    * compiler in the Visual Stuido (tested on VS 2013 Community)
    * compiler Intel ICC 13.0.1

    it will display the number "1". And I thought it is logical, since
    function type, being substituted argument in another function,
    acquires
    the properties of a pointer type.
    On newer versions of compilers mentioned (except for VS and ICC)
    behavior has changed and now this code for Clang 3.5 (or higher), GCC
    4.9 (or higher) displays the number "2". If you remove the second
    overload, then the mentioned versions of GCC and Clang error occurs:
    "Forming pointer to qualified function type"
    I understand why but doubt whether this rule applies in this context.

    In particular, it would be interesting to know whether the behavior of
    the new and old versions of the compilers conforms to C++ Standard.

    My interpretation of the code is that it should be required to be
    ill-formed after acceptance of

    http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1417

    because it is not valid to form a pointer to a function with
    cv-qualifier-seq (In the example: 'void() const'). It is somewhat
    interesting to note that this interpretation also depends on the
    semantics of function parameter decay which is also discussed by

    http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1668

    But even if the details of CWG 1668 are not clarified yet, I believe it
    is save to assume that the transformation mentioned in [dcl.fct] p5

    "After determining the type of each parameter, any parameter of type
    “array of T” or of function type T is adjusted to be “pointer to T”.

    would produce an invalid type and would require a diagnostics, because
    the function type is 'void() const'. The wording details of CWG 1668
    will hopefully clarify further details, e.g. whether the substituation
    attempt for dependent function parameters will effectively lead to
    SFINAE, but regardless of that detail, the presented example doesn't
    provide any third valid fall-back for 'probe' that could be selected, so

    there should be no function probe that could be selected by overload resolution.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)