Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Why does C allow structs to have a tag? Date: Mon, 06 Sep 2021 05:09:48 -0700 Organization: A noiseless patient Spider Lines: 85 Message-ID: <8635qhx5v7.fsf@linuxsc.com> References: <867dijb22a.fsf@linuxsc.com> <86a6mt8g69.fsf@linuxsc.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="3555d3b4345d8bc729243ac3d8ab4b79"; logging-data="30354"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+v+2xradM0napZjqJXtKrXqJO6u4RREZo=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:Blv+h0rj8fbqvPxdgiQbVmzmTwU= sha1:zuyIIUa6ymxgjzcZKZoAlPz1mxI= Xref: csiph.com comp.lang.c:162638 John Bode writes: > On 7/11/21 2:26 AM, Tim Rentsch wrote: > >> John Bode writes: >> >>> On 6/24/21 12:33 PM, Tim Rentsch wrote: >>> >>>> John Bode writes: >>>> >>>> [...] >>>> >>>>> To reiterate a point I make a lot - typedef on its own creates >>>>> leaky abstractions. If I need to know that I have to use the >>>>> `.` or `->` operator on something, I'd rather have it declared >>>>> as `struct A foo;` or `struct B *ptr;` instead of a type name >>>>> that doesn't convey struct-ness at all. Same reason I don't >>>>> like it when people hide pointers behind typedefs - I once spent >>>>> half a day chasing my tail because somebody created a typedef >>>>> name for a pointer type and used that as a template parameter >>>>> for a vector in C++, such that when I was using an iterator I >>>>> needed to write >>>>> >>>>> (*it)->do_something(); >>>>> >>>>> However, since the typedef name didn't indicate pointer-ness *at >>>>> all*, I wound up writing >>>>> >>>>> it->do_something(); >>>>> >>>>> and g++ vomited up hundreds of incomprehensible error messages >>>>> that basically boiled down to "you need to use a * here, dummy". >>>> >>>> Sounds to me like the culprit is C++, not typedefs. >>> >>> g++ doesn't handle errors in template parameters very well and >>> generates a *lot* of hard-to-follow error messages for relatively >>> simple mistakes. And at the time I was still relatively >>> inexperienced with C++, which didn't help. >>> >>> But the typedef name (or, more properly, the incomplete and leaky >>> abstraction introduced by that typedef name) was the actual >>> culprit. [...] >> >> I stand by my earlier claim that the culprit here is C++ >> rather than typedefs. > > I honestly don't know how to make it any clearer. I lost time due > to using the wrong syntax. I was using the wrong syntax because the > information I needed in order to use the right syntax was hidden > from me. That's not a function of it being C++, that's a function > of the abstraction not being complete. You reported a case in a C++ program where confusion of pointer versus non-pointer generated "hundreds of incomprehensible error messages", causing you to lose time tracking down the problem. Consider an analogous case in C: it.do_something(); with 'it' having the pointer-concealing-typedef'ed type. In gcc this expression produce a one-line error message: what.c:7:15: error: 'it' is a pointer; did you mean to use '->'? and in clang pretty much the same. If we consider a case with a type that is a pointer to the pointer-concealing-typedef'ed type, such as: it->do_something(); where we should have used (*it)->do_something(); again gcc gives a one-line error message: what.c:11:15: error: '*it' is a pointer; did you mean to use '->'? and clang again pretty much the same. In all of these cases fixing the problem takes perhaps 15 to 30 seconds. By far the larger part of the problem is C++, not any "hidden" pointerness, which is why I say that the culprit here is C++ rather than typedefs.