Date: Fri, 26 May 2023 11:23:18 +0200
On Wed, May 24, 2023 at 8:07 PM Jens Maurer via SG15 <sg15_at_[hidden]>
wrote:
>
> On 24/05/2023 16.23, Daniel Ruoso wrote:
> > Em ter., 23 de mai. de 2023 às 17:36, Jens Maurer
> > <jens.maurer_at_[hidden]> escreveu:
> >> In any case, I would really appreciate a very specific,
> >> concrete example (exemplary source code) of the troubles
> >> you seem to be talking about. If three two-line files
> >> suffice to show the principles, that's good enough.
> >> I have the gut feeling there is an assumption hidden somewhere
> >> in your arguments that might not be universally shared.
> >
> > ```foo.h
> > #ifdef FOO_ARG_1
> > import <bar.h>
> > #elif FOO_ARG_2
> > import <baz.h>
> > #endif
> > ```
> >
> > ```qux.h
> > #define FOO_ARG_1
> > #include <foo.h>
> > ```
> >
> > ```qux.cpp
> > #include <qux.h>
> > ```
>
> Thanks for the example!
>
> > Now, let's imagine that we declare `foo.h` to be an importable header.
>
> And that's a user bug right there. foo.h is simply not supposed to
> be treated as an importable header.
I disagree pretty strongly for both philosophical and practical reasons. I
think that the vast majority of headers should be treated as importable,
the only exceptions are weird cases that really need textual inclusion like
X-macros and the like.
Philosophical: My take is that by declaring foo.h to be an importable
header (and one where #includes should be treaded as imports) is that you
want foo.h to have a single consistant meaning for an entire build (or at
least for each program image). In this world you would be saying that qux.h
doesn't get to change the meaning of foo.h, it must take the meaning
defined by the builder of the program image. It is free to define FOO_ARG1
for _its own use_ but that is explicitly prevented from affecting foo.h.
And that is a good thing!
Practical: If foo.h isn't importable, then basically no headers are, and
that includes things we require to be importable like <vector>! To see
this, lets try replacing the metasyntactic variable with concrete cases. I
argue that both of these are equivalent to foo.h:
// <vector>
#ifdef _DEBUG
# include <debug/vector>
#else
# include <release/vector>
#endif
// my_header.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
#include <other_header.h>
// ... stuff
#endif
Can you really come up with a rule that leaves both of those as valid
importable headers but foo.h as not?
Perhaps we mostly disagree on the framing though. My take is that the
problem here _isn't_ that foo.h was declared as importable. The problem is
that qux.h is trying to change the meaning of the foo.h header. And that is
*really* a problem today in the world of textual source inclusion because
it basically guarantees an ODR violation (hopefully one that is harmless in
practice, but still normatively IFNDR). Making that #include into an import
may have even *fixed* the problem! Really it is only a problem if qux.h
*depends* on the meaning of foo.h being changed, that than it just being a
suggestion or preference. As long as it is OK using the single meaning of
foo.h, then there is no problem here.
> You're welcome to attempt to
> support such misguided code in your build system, but that does not
> establish any argument at all that the feature "importable headers"
> should be removed from the C++ standard.
>
> Analogy: You can't divide by 0. That doesn't mean we should remove
> 0 from the set of valid integers, because 0 has plenty of good uses
> elsewhere.
>
> And for the avoidance of doubt: Absent substantially more
> convincing rationale than examples such as the one above,
> I'll strongly oppose a proposal attempting to remove the
> "importable headers" feature from the C++ standard, including
> encouraging CWG to form a disrupting consensus opinion in the
> unlikely event that such a proposal would reach that stage.
>
> Jens
> _______________________________________________
> SG15 mailing list
> SG15_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg15
>
wrote:
>
> On 24/05/2023 16.23, Daniel Ruoso wrote:
> > Em ter., 23 de mai. de 2023 às 17:36, Jens Maurer
> > <jens.maurer_at_[hidden]> escreveu:
> >> In any case, I would really appreciate a very specific,
> >> concrete example (exemplary source code) of the troubles
> >> you seem to be talking about. If three two-line files
> >> suffice to show the principles, that's good enough.
> >> I have the gut feeling there is an assumption hidden somewhere
> >> in your arguments that might not be universally shared.
> >
> > ```foo.h
> > #ifdef FOO_ARG_1
> > import <bar.h>
> > #elif FOO_ARG_2
> > import <baz.h>
> > #endif
> > ```
> >
> > ```qux.h
> > #define FOO_ARG_1
> > #include <foo.h>
> > ```
> >
> > ```qux.cpp
> > #include <qux.h>
> > ```
>
> Thanks for the example!
>
> > Now, let's imagine that we declare `foo.h` to be an importable header.
>
> And that's a user bug right there. foo.h is simply not supposed to
> be treated as an importable header.
I disagree pretty strongly for both philosophical and practical reasons. I
think that the vast majority of headers should be treated as importable,
the only exceptions are weird cases that really need textual inclusion like
X-macros and the like.
Philosophical: My take is that by declaring foo.h to be an importable
header (and one where #includes should be treaded as imports) is that you
want foo.h to have a single consistant meaning for an entire build (or at
least for each program image). In this world you would be saying that qux.h
doesn't get to change the meaning of foo.h, it must take the meaning
defined by the builder of the program image. It is free to define FOO_ARG1
for _its own use_ but that is explicitly prevented from affecting foo.h.
And that is a good thing!
Practical: If foo.h isn't importable, then basically no headers are, and
that includes things we require to be importable like <vector>! To see
this, lets try replacing the metasyntactic variable with concrete cases. I
argue that both of these are equivalent to foo.h:
// <vector>
#ifdef _DEBUG
# include <debug/vector>
#else
# include <release/vector>
#endif
// my_header.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
#include <other_header.h>
// ... stuff
#endif
Can you really come up with a rule that leaves both of those as valid
importable headers but foo.h as not?
Perhaps we mostly disagree on the framing though. My take is that the
problem here _isn't_ that foo.h was declared as importable. The problem is
that qux.h is trying to change the meaning of the foo.h header. And that is
*really* a problem today in the world of textual source inclusion because
it basically guarantees an ODR violation (hopefully one that is harmless in
practice, but still normatively IFNDR). Making that #include into an import
may have even *fixed* the problem! Really it is only a problem if qux.h
*depends* on the meaning of foo.h being changed, that than it just being a
suggestion or preference. As long as it is OK using the single meaning of
foo.h, then there is no problem here.
> You're welcome to attempt to
> support such misguided code in your build system, but that does not
> establish any argument at all that the feature "importable headers"
> should be removed from the C++ standard.
>
> Analogy: You can't divide by 0. That doesn't mean we should remove
> 0 from the set of valid integers, because 0 has plenty of good uses
> elsewhere.
>
> And for the avoidance of doubt: Absent substantially more
> convincing rationale than examples such as the one above,
> I'll strongly oppose a proposal attempting to remove the
> "importable headers" feature from the C++ standard, including
> encouraging CWG to form a disrupting consensus opinion in the
> unlikely event that such a proposal would reach that stage.
>
> Jens
> _______________________________________________
> SG15 mailing list
> SG15_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg15
>
Received on 2023-05-26 09:23:33