On Sat, Feb 15, 2020 at 7:07 PM Arthur O'Dwyer <arthur.j.odwyer@gmail.com> wrote:
Hi Jim,

Sadly your idea doesn't work in C++, because C++ has member functions.  That is, we can write things like this:

struct Widget {
    void reset();  // reset the widget
};
[...]
std::unique_ptr<Widget> p = std::make_unique<Widget>();
p->reset();  // reset the pointed-to widget by calling Widget::reset() member function
p.reset();  // reset the pointer's own value to nullptr


But, isn't the .reset() implemented on the unique_ptr<> template as a operator. override?  which takes precedence over the default behavior...

 a function member is otherwise the same as any field value, other than being allocated by the compiler/linker instead of a user value ...
'void f(void);'  vs 'void (*pf)(void);'  the latter of which can be used in C structures also.

So -> and . literally have different meanings, and you can't combine them in the way you're trying to.

(This would be a good example to show to your C colleagues when they talk about . versus -> being a "stumbling block.")

HTH,
Arthur

On Sat, Feb 15, 2020 at 3:35 PM J Decker via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
I would like to see the operators '.' and '->' inspect their left hand value's type and generate the appropriate base address from it added to C.
Since I use C++ compiler often to compile C code as a strongly typed C compiler, this should be suggested here too.

See end for additional C++ comments
---

My proposal is to make the operator '.' consider the type of the left hand value and behave as '.' or '->' appropriately. I could say, make '.' and '->' equivalent, however, the desire would be to migrate to just using '.' operators and dropping the -> altogether(sometime, in the far future, removal/deprecation is not part of this proposal), since it would become redundant.  Maybe it becomes a styling mechanism.

This change could be shared with C++ to make sure that c2x(and later) code could still be compiled with C++.  C++ Does have operator overloading, but the compiler should be able to determine if the compiler is operating on a structure/union/(class) or a pointer to(array of) struct/union/(class);(see end)

In C, in order for either '.' or '->' to be used, the left hand value must be a completely defined structure or union, or a pointer to a structure or union.  A pointer to a pointer cannot be used with either of those, requiring some other dereference operation to get down to 1(->) or 0(.) levels of indirection.

In either case, the compiler (GCC for instance) has the complete type information of the left hand value, and can inspect whether the value is a reference to a instance of a structure or union, or a pointer to a structure or union. In the first case(instance) the address comes from the local function address space (stack pointer) or some other memory location computed by the compiler, in the second case, the address is given by the value of the left hand value instead of computed by the compiler/linker, and in both cases, the right hand value is a name of a field in a structure/union, which is the additional offset to apply to the base address.   

The modification to the GCC C compiler (9.x) is nearly trivial.  The modification to make '.' and '->' work the same, and to inspect the type of the left hand value and use the 'get variable location' or 'get value of pointer' appropriately.  Because of the requirement of a complete type (incomplete types used with '.' or '->' generate an error in all C compilers), every compiler must know the type and it's definition of the left value to use the right hand name in.  (the right hand value must be a name within a(the?) structure/union, and cannot be a computed value, ie  `ptr->(1+3)` is not valid)

This change would have no impact on existing code.  Everything that used to compile with a C compiler would continue to compile with a C compiler.

Code written against the new standard would potentially not be compatible with previous standards.  

---
My reasoning for approaching this, or even thinking about it, was from having taken C code which I ported to JS by replacing `TYPE name` with `val name` and '->' to '.', and it was 95% done; other than the function signatures.  Taking this code and bringing it back to C becomes and issue because of the loss of -> operators; so I began considering why the implied type information form Javascript wouldn't already exist in the C compiler, since everything must be 'pre-typed', or defined ahead of time with its full type information, that the compiler couldn't also do the 'smart' thing based on the type of the value of the left hand expression.

I asked on IRC in ##C and ##programming about this idea, and someone mentioned that the usage of '.' and '->' to programmers just learning the language is very often a stumbling block... since to they do 'the same thing' it's hard to understand why '.' and '->' are even different... Eventually, you understand that they are different because you declared either a 'static' instance of a thing ( FILE a ) vs creating a pointer to a thing ( FILE* pa ).  

There is the `*` that can dereference a pointer, so you can still use '.' everywhere and never use `->',  `(*thing).` ; or `thing[0].` ; however that coding style doesn't improve the ability to back-port C ported to JS back to C.  Those mechanisms would still work, since they result in a reference to a structure or union instance instead of the pointer to the same instance.

Conversely, it was suggested that losing the distinction of  '.' or '->' operators loses information about the types of a thing you are working on.  'pointer->struc.member.something->name' you just 'know' that there is a pointer to a structure that is a single (large) of other structures that has a pointer to a name... so you 'know' it's only 2 memory locations you're dealing with.

---
===
C++ notes.
This would only apply for the builtin/default handlers for the '.' and '->' operators.  Those operator overrides that have been defined by a class/struct should still expect to do their same function.  The function of '.' and '->' should still be overloadable with separate handlers; although the C++ code doesn't interact at a compiler level here, and would have no way (?) of generating, 'use base address of structure instance' or 'read value from variable and use as base address of structure'.

I've not followed the development and growth of C++ with all the safe pointer extensions... I am far from a deep C++ guru.

Jim B
https://github.com/d3x0r ( it's pronouced Decker)

--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals