Date: Fri, 28 Feb 2020 19:25:21 -0800
On Fri, Feb 28, 2020 at 10:07 AM Patrice Roy via Liaison <
liaison_at_[hidden]> wrote:
> My initial point in response to your message was to point out that in C++,
> there are cases where making '.' behave as '->' does today breaks otherwise
> correct code and introduces ambiguity.
>
> C++ users, contrary to C# or Java users, have the option of using objects
> directly or indirectly. In C# (excluding structs) and Java, all objects are
> accessed through indirect means. On the other hand, for a C++ programmer
> using a smart pointer such as unique_ptr<T>, the ability to distinguish the
> services exposed by that object (using '.') and those exposed by the
> pointee (using '->') carries meaning, and that distinction is not readily
> accessible in some other languages this proposal refers to.
>
> Please also note that operator-> can be (and is sometimes) overloaded in
> C++ classes.
>
I'm failing to communicate 'where it is now an error'. The proposed change
really only affects things which right now generate a compiler error; maybe
demote to a warning, and do what the error message suggests and use -> ?
Then the warning can be disabled, or kept so you have compiler diagnostics
without implementing a linter into the build chain.
If the value is a (raw) pointer the first -> applies to dereference the
pointer, and '.' is an error,
if the value is an instance of a struct/class/union -> accesses the
operator and . accesses the members of the struct.
There is no occasion where '.' would also mean 'call operator()'; and
having analyzed this I should entirely rewrite comments about that.
The smart pointer types are instances of classes that represent pointers
that have properties, but '.' just accesses that instance. If there was
was a `unique_ptr<C> *pupC`? and in that case '.' could be used instead of
->... but the compiler doesn't have to consider the operator() yet because
it's still a pointer to a class.
--- test.cc ----
struct S {
struct S *next;
struct S **me;
operator->()
};
struct S_with_functions {
struct S_width_functions *next;
struct S_width_functions **me;
void unlink( void ) { me[0] = next; }
S_with_functions() {
/* structs are the same as classes, except default protection... */
next = 0;
me = &next;
}
};
class C {
public:
class C *next;
class C **me;
C() {
}
};
void f( void ) {
struct S c_S;
S cpp_S;
C cpp_C;
c_S.me = &c_S.next;
cpp_S.me = &cpp_S.next;
cpp_C.me = &cpp_C.next;
c_S.me[0]->next = &cpp_S; // the old way; legal
c_S.me[0].next = cpp_S.me.next; // error
/*
# gcc test.cc
test.cc: In function 'void f()':
test.cc:35:12: error: request for member 'next' in '* c_S.S::me', which is
of pointer type 'S*' (maybe you meant to use '->' ?)
c_S.me[0].next = cpp_S.me.next; // error
^~~~
test.cc:35:28: error: request for member 'next' in 'cpp_S.S::me', which is
of non-class type 'S**'
c_S.me[0].next = cpp_S.me.next; // error
^~~~
*/
cpp_S.me[0]->next = &cpp_S; // the old way; legal
cpp_S.me[0].next = c_S.me.next; // error
/*
test.cc:38:14: error: request for member 'next' in '* cpp_S.S::me', which
is of pointer type 'S*' (maybe you meant to use '->' ?)
cpp_S.me[0].next = c_S.me.next; // error
^~~~
test.cc:38:28: error: request for member 'next' in 'c_S.S::me', which is of
non-class type 'S**'
cpp_S.me[0].next = c_S.me.next; // error
^~~~
*/
}
liaison_at_[hidden]> wrote:
> My initial point in response to your message was to point out that in C++,
> there are cases where making '.' behave as '->' does today breaks otherwise
> correct code and introduces ambiguity.
>
> C++ users, contrary to C# or Java users, have the option of using objects
> directly or indirectly. In C# (excluding structs) and Java, all objects are
> accessed through indirect means. On the other hand, for a C++ programmer
> using a smart pointer such as unique_ptr<T>, the ability to distinguish the
> services exposed by that object (using '.') and those exposed by the
> pointee (using '->') carries meaning, and that distinction is not readily
> accessible in some other languages this proposal refers to.
>
> Please also note that operator-> can be (and is sometimes) overloaded in
> C++ classes.
>
I'm failing to communicate 'where it is now an error'. The proposed change
really only affects things which right now generate a compiler error; maybe
demote to a warning, and do what the error message suggests and use -> ?
Then the warning can be disabled, or kept so you have compiler diagnostics
without implementing a linter into the build chain.
If the value is a (raw) pointer the first -> applies to dereference the
pointer, and '.' is an error,
if the value is an instance of a struct/class/union -> accesses the
operator and . accesses the members of the struct.
There is no occasion where '.' would also mean 'call operator()'; and
having analyzed this I should entirely rewrite comments about that.
The smart pointer types are instances of classes that represent pointers
that have properties, but '.' just accesses that instance. If there was
was a `unique_ptr<C> *pupC`? and in that case '.' could be used instead of
->... but the compiler doesn't have to consider the operator() yet because
it's still a pointer to a class.
--- test.cc ----
struct S {
struct S *next;
struct S **me;
operator->()
};
struct S_with_functions {
struct S_width_functions *next;
struct S_width_functions **me;
void unlink( void ) { me[0] = next; }
S_with_functions() {
/* structs are the same as classes, except default protection... */
next = 0;
me = &next;
}
};
class C {
public:
class C *next;
class C **me;
C() {
}
};
void f( void ) {
struct S c_S;
S cpp_S;
C cpp_C;
c_S.me = &c_S.next;
cpp_S.me = &cpp_S.next;
cpp_C.me = &cpp_C.next;
c_S.me[0]->next = &cpp_S; // the old way; legal
c_S.me[0].next = cpp_S.me.next; // error
/*
# gcc test.cc
test.cc: In function 'void f()':
test.cc:35:12: error: request for member 'next' in '* c_S.S::me', which is
of pointer type 'S*' (maybe you meant to use '->' ?)
c_S.me[0].next = cpp_S.me.next; // error
^~~~
test.cc:35:28: error: request for member 'next' in 'cpp_S.S::me', which is
of non-class type 'S**'
c_S.me[0].next = cpp_S.me.next; // error
^~~~
*/
cpp_S.me[0]->next = &cpp_S; // the old way; legal
cpp_S.me[0].next = c_S.me.next; // error
/*
test.cc:38:14: error: request for member 'next' in '* cpp_S.S::me', which
is of pointer type 'S*' (maybe you meant to use '->' ?)
cpp_S.me[0].next = c_S.me.next; // error
^~~~
test.cc:38:28: error: request for member 'next' in 'c_S.S::me', which is of
non-class type 'S**'
cpp_S.me[0].next = c_S.me.next; // error
^~~~
*/
}
---- J > I think it would at least be necessary to address these (important) > questions in the proposal, should it become something more formal. > > Cheers! > > Le ven. 28 févr. 2020 à 11:41, J Decker via Liaison < > liaison_at_[hidden]> a écrit : > >> >> >> On Fri, Feb 28, 2020 at 5:34 AM Bjarne Stroustrup <bjarne_at_[hidden]> >> wrote: >> >>> How do you know that having . and -> roughly mean the same would be a >>> benefit to the community at large? >>> >>> For example, people assume that -> implies reference semantic and >>> potential sharing, whereas . implies value semantic (except for non-const >>> reference parameters) and lack of sharing. That could be more significant >>> than the convenience of having just a single operator. >>> >>> The burden of proof is on the proposer of a change. >>> >> It's hard to show how a change to C might play out; given 50 some years >> of history it's hardly even worth bothering to change. >> I'm understanding that it is less meaningful of a change to C++ other >> than as a compatibility should C accept such a thing. >> It's encouraged practice to use newer smart pointer types, and I have a >> module for V8 which uses those all over, and certainly the use of '.' or >> '->' means different things, and it's still enforced by the compiler to use >> the right one. I'm not entirely sure that there would even be much change >> to code developed in C++. >> >> This is honestly a new idea only a few months old, as I was reflecting on >> 'why IS `((Something*)ptr).` an error' ? Why are there two operators that >> aren't even interchangeable in context, and that there's only one choice to >> use. I have spent a few years with C#, and recently ES6+(not even >> technically JS), and '.' seems easy enough to use, even when there's a >> mixture of C# structs(instance value types) and classes (reference, always >> referred by pointer), and it's not really a loss to inadvertently look in a >> value type, but then, the debugger reports 'null exception on this part of >> this expression' so you rarely even have to guess what it was. I can't >> really demonstrate what sort of effect this would have on development; or >> even how it would change existing things. (libz is still written with K&R >> style function declarations). Certainly everything that has worked would >> still work. >> >> Certainly, having already assigned a sort of meaning to them back in the >> 90's, I haven't ever really even questioned it until now. >> >> It's my hypothesis that at the time this was developed, data driven >> programming (where the type of the data is [with] the data), and type >> inspection was not a consideration, but more, that one type needs to be >> another type ( float a = (float)213 ), and that C was more about coercion >> than inspection, so since a pointer to a thing and a thing definitely >> aren't the same, they have to be operated on differently; while conversely >> it can be said just look at the type of the operand and do the right thing. >> >>> On 2/28/2020 7:57 AM, J Decker via Liaison wrote: >>> >>> >>> >>> On Thu, Feb 27, 2020 at 10:21 PM Uecker, Martin < >>> Martin.Uecker_at_[hidden]> wrote: >>> >>>> Am Donnerstag, den 27.02.2020, 22:15 -0800 schrieb J Decker: >>>> > On Thu, Feb 27, 2020 at 10:09 PM Uecker, Martin via Liaison < >>>> > liaison_at_[hidden]> wrote: >>>> > >>>> > > >>>> > > It is useful to have the information about >>>> > > whether something is a pointer or not and the >>>> > > difference between '.' and '->' makes it clear. >>>> > > >>>> > >>>> > >>>> https://gist.github.com/d3x0r/f496d0032476ed8b6f980f7ed31280da#the-meaning-of---and-- >>>> <https://urldefense.proofpoint.com/v2/url?u=https-3A__gist.github.com_d3x0r_f496d0032476ed8b6f980f7ed31280da-23the-2Dmeaning-2Dof-2D-2D-2Dand-2D-2D&d=DwMFaQ&c=u6LDEWzohnDQ01ySGnxMzg&r=-ypbxfA15hWRWp5mAlnCkA&m=r-p2sPYtgW9vx52cY3llBBeul0O7y8wIcs4dNMJTs-s&s=aS1qWqzUrPnjhstqWNjf-6xlWXnxaeOmcvoKpEEsvNQ&e=> >>>> > >>>> > it reduces the points you have to check, but it's really not all that >>>> > useful when dealing with a variety of languages.. '.' just becomes >>>> another >>>> > place to check validity of the expression's values... So yes, it >>>> increases >>>> > the potential things to check... but then, nothing stylistically >>>> prevents >>>> > you from continuing to denote that. >>>> >>>> If it not enforced by the language, the information >>>> is unreliable. This is even worse than not having it. >>>> >>> >>> I know, this is still really just me... https://github.com/d3x0r/sack >>> <https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_d3x0r_sack&d=DwMFaQ&c=u6LDEWzohnDQ01ySGnxMzg&r=-ypbxfA15hWRWp5mAlnCkA&m=r-p2sPYtgW9vx52cY3llBBeul0O7y8wIcs4dNMJTs-s&s=cj_DZuKqU0h8EMZ-cbdK1zFGeB5MXNE8gH2GRuwSDXg&e=> and >>> some arbitrary source... >>> https://github.com/d3x0r/SACK/blob/master/src/idlelib/idle.c >>> <https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_d3x0r_SACK_blob_master_src_idlelib_idle.c&d=DwMFaQ&c=u6LDEWzohnDQ01ySGnxMzg&r=-ypbxfA15hWRWp5mAlnCkA&m=r-p2sPYtgW9vx52cY3llBBeul0O7y8wIcs4dNMJTs-s&s=NfvK6o7zRd6CS7kuhTho1ll5pWV7u8pgpWd9EJKALi8&e=> >>> >>> there's a flags structure that is just instanced in another struct >>> check->flags.bDispatched = 1 >>> >>> that's used a few times, all other accesses are `->` >>> >>> can you provide an example of where this information is useful? >>> Porting the above to c2x it wouldn't change how many things have to be >>> looked at as suspect... >>> OR what is the information that distinct operators provides rather than >>> using '.' everywhere (except, I suppose in C++ where you want to access an >>> operator override on a pointer type.. ) >>> >>> class x { >>> /* operaror->() ... */ >>> }; >>> class x *px; >>> >>> px->x; (use operator?) >>> >>> >>> >>>> Best, >>>> Martin >>> >>> _______________________________________________ >> Liaison mailing list >> Liaison_at_[hidden] >> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison >> Link to this post: http://lists.isocpp.org/liaison/2020/02/0054.php >> > _______________________________________________ > Liaison mailing list > Liaison_at_[hidden] > Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison > Link to this post: http://lists.isocpp.org/liaison/2020/02/0055.php >
Received on 2020-02-28 21:28:16