• Re: C23 auto x C++ auto.

    From Michael S@21:1/5 to Thiago Adams on Sun May 26 17:23:07 2024
    On Sun, 26 May 2024 10:49:30 -0300
    Thiago Adams <thiago.adams@gmail.com> wrote:

    I think most people is not aware of this:

    From 3096 C23 draft

    "
    6.7.9 Type inference
    ...
    2 For such a declaration that is the definition of an object the
    init- declarator shall have the form

    direct-declarator = assignment-expression
    "

    Basically "direct-declarator" differs from "declarator" because it
    does not contains pointer.

    Then the type inference using auto and pointer is something undefined
    in C23.

    struct node{
    struct node * next;

    };
    int main(){
    struct node node = {};
    auto * p = node.next;
    }

    <source>:7:4: error: 'auto' requires a plain identifier, possibly
    with attributes, as declarator
    7 | auto * p = node.next;
    | ^~~~

    This differs from C++.



    Differs in positive way. Less confusing.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bonita Montero on Sun May 26 18:10:32 2024
    On 26/05/2024 16:22, Bonita Montero wrote:
    Am 26.05.2024 um 15:49 schrieb Thiago Adams:
    I think most people is not aware of this:

     From 3096 C23 draft

    "
    6.7.9 Type inference
    ...
      2 For such a declaration that is the definition of an object the
    init-    declarator shall have the form

        direct-declarator = assignment-expression
    "

    Basically "direct-declarator" differs from "declarator" because it
    does not contains pointer.

    Then the type inference using auto and pointer is something undefined
    in C23.

    struct node{
         struct node * next;

    };
    int main(){
        struct node node = {};
        auto * p = node.next;
    }

    <source>:7:4: error: 'auto' requires a plain identifier, possibly with
    attributes, as declarator
         7 |    auto * p = node.next;
           |    ^~~~

    This differs from C++.



    I don't know what type inference in C is good for since the type names
    in C are usually short. If I have short typenames in C++ I don't use
    type inference. Type-inference makes sense to make such things shorter
        typename map<string, string>::const_iterator it = map.cbegin();
    This doesn't happen in C.


    "typeof" and "auto" have been available forever as gcc extensions (where
    "auto" was spelt "__auto_type", since of course "auto" had another
    meaning in C until C23). One use-case for C is in macros that handle
    multiple types, but I expect people have done other things with them too.

    It would have been nice to see statement expressions included in C23, as
    they have been in gcc for ages:

    #define max(a,b) \
    ({ __auto_type _a = (a); \
    __auto_type _b = (b); \
    _a > _b ? _a : _b; })


    In general, it's just another tool that could be useful in writing code
    that's a bit more flexible.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blue-Maned_Hawk@21:1/5 to Bonita Montero on Mon May 27 05:53:39 2024
    Bonita Montero wrote:

    I don't know what type inference in C is good for since the type names
    in C are usually short. If I have short typenames in C++ I don't use
    type inference. Type-inference makes sense to make such things shorter
    typename map<string, string>::const_iterator it = map.cbegin();
    This doesn't happen in C.

    Type-inference in C is useful for the same sole reason that type-inference
    has any use anywhere else: preventing repetition of a typename.



    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    Current weather: On fire

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blue-Maned_Hawk@21:1/5 to David Brown on Mon May 27 05:55:10 2024
    David Brown wrote:

    It would have been nice to see statement expressions included in C23, as
    they have been in gcc for ages:

    #define max(a,b) \
    ({ __auto_type _a = (a); \
    __auto_type _b = (b); \
    _a > _b ? _a : _b; })

    As i understand it, WG14's plan is to eventually get lambdas into standard
    C so as to unify statementexprs with Clang's Blocks and GCC's local subroutines.



    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    The world is made of quacks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to All on Mon May 27 11:05:34 2024
    On 27/05/2024 07:55, Blue-Maned_Hawk wrote:
    David Brown wrote:

    It would have been nice to see statement expressions included in C23, as
    they have been in gcc for ages:

    #define max(a,b) \
    ({ __auto_type _a = (a); \
    __auto_type _b = (b); \
    _a > _b ? _a : _b; })

    As i understand it, WG14's plan is to eventually get lambdas into standard
    C so as to unify statementexprs with Clang's Blocks and GCC's local subroutines.


    I've certainly seen suggestions for lambdas in C. I'm not sure that it
    is a great idea to add such high-level features to C - if we want to
    work in C but with lambdas, C++ already supports that. But "blocks"
    (borrowed from Objective-C, IIRC) are more advanced than gcc's statement expressions, so I suppose lambdas are a reasonable superset of these
    three extensions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Thiago Adams on Mon May 27 11:01:51 2024
    On 26/05/2024 18:38, Thiago Adams wrote:
    Em 5/26/2024 1:10 PM, David Brown escreveu:
    On 26/05/2024 16:22, Bonita Montero wrote:
    Am 26.05.2024 um 15:49 schrieb Thiago Adams:
    I think most people is not aware of this:

     From 3096 C23 draft

    "
    6.7.9 Type inference
    ...
      2 For such a declaration that is the definition of an object the
    init-    declarator shall have the form

        direct-declarator = assignment-expression
    "

    Basically "direct-declarator" differs from "declarator" because it
    does not contains pointer.

    Then the type inference using auto and pointer is something
    undefined in C23.

    struct node{
         struct node * next;

    };
    int main(){
        struct node node = {};
        auto * p = node.next;
    }

    <source>:7:4: error: 'auto' requires a plain identifier, possibly
    with attributes, as declarator
         7 |    auto * p = node.next;
           |    ^~~~

    This differs from C++.



    I don't know what type inference in C is good for since the type names
    in C are usually short. If I have short typenames in C++ I don't use
    type inference. Type-inference makes sense to make such things shorter
         typename map<string, string>::const_iterator it = map.cbegin(); >>> This doesn't happen in C.


    "typeof" and "auto" have been available forever as gcc extensions
    (where "auto" was spelt "__auto_type", since of course "auto" had
    another meaning in C until C23).  One use-case for C is in macros that
    handle multiple types, but I expect people have done other things with
    them too.

    It would have been nice to see statement expressions included in C23,
    as they have been in gcc for ages:

    #define max(a,b) \
       ({ __auto_type _a = (a); \
           __auto_type _b = (b); \
         _a > _b ? _a : _b; })


    In general, it's just another tool that could be useful in writing
    code that's a bit more flexible.


    I am trying to remember the situation where typeof cannot be used,
    justifying the existence of auto other than "easy to read".

    "Easy to read" is a pretty good justification for a feature, IMHO.

    The gcc documentation at
    <https://gcc.gnu.org/onlinedocs/gcc/Typeof.html> lists two more
    advantages of "__auto_type" over "typeof" (in situations where either
    could be used) :

    """
    * Each argument to the macro appears only once in the expansion of the
    macro. This prevents the size of the macro expansion growing
    exponentially when calls to such macros are nested inside arguments of
    such macros.

    * If the argument to the macro has variably modified type, it is
    evaluated only once when using __auto_type, but twice if typeof is used.
    """

    (This last one is only likely to be an issue if you are trying hard to
    make your code painful to test the corner-cases of VLAs.)



     #define max(a,b) \
        ({ typeof(a) _a = (a); \
            typeof(a) _b = (b); \
          _a > _b ? _a : _b; })

    I think for function calls typeof can be a little confusing because the arguments.

    typeof(f(arg1, arg2)) r = f(arg1, arg2);
    auto r = f(arg1, arg2);


    That looks like another good case. The results (the type of r) will be
    the same, and "f" will only be evaluated once, but it certainly doesn't
    look nice. And it gets messy if there are macros involved.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Thiago Adams on Fri Jun 7 00:50:51 2024
    On Sun, 26 May 2024 13:38:08 -0300, Thiago Adams wrote:

    I am trying to remember the situation where typeof cannot be used,
    justifying the existence of auto other than "easy to read".

    As one example, if the type definition includes “const”, then trying to
    use “typeof” to define a variable to assign to will of course fail. That’s
    why you have “typeof_unqual”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Fri Jun 7 00:46:07 2024
    On Mon, 27 May 2024 11:05:34 +0200, David Brown wrote:

    But "blocks" (borrowed from Objective-C, IIRC) are more advanced than
    gcc's statement expressions, so I suppose lambdas are a reasonable
    superset of these three extensions.

    Now all we need is gensym, and then we can do away with #define-style
    macros and just use inline statement expressions instead.

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