Boost logo

Boost :

From: Ruben Perez (rubenperez038_at_[hidden])
Date: 2024-12-22 15:01:00


On Sun, 22 Dec 2024 at 16:45, Peter Dimov <pdimov_at_[hidden]> wrote:
>
> Ruben Perez wrote:
> > > By the way, I posted about the optional `export` idea to the committee
> > > mailing list, and Michael Spencer replied and basically said "don't".
> > >
> > > "My suggestion is to do either `export import <boost/foo.hpp>;` in the
> > > module if you are ok with getting extra declarations, or `export using ...` like
> > libc++ does.
> > > Trying to textually include a header into the purview of a named
> > > module is fraught with issues."
> > >
> > > Since everything that's textually included becomes attached to the
> > > named module, it's too easy to create ODR violations.
> > >
> > > But, apparently, Clang doesn't like header units, so the above is also
> > > not quite optimal.
> >
> > I'd like to understand more about this, since this is the approach I have been
> > following (and AFAIK, the one that John Maddock and Matt Borland followed,
> > too). What would be the possible ODR violations here? Does he refer to the
> > case where we forget to #ifdef-out an include for a dependency?
>
> Yes. Assume for a moment that we don't have `import std;` available. In that
> case, an #include <algorithm> from one of our headers would attach all its
> declarations and definitions to our named module. When a user imports our
> module and includes <algorithm>, that's an ODR violation.
>
> The way to avoid this is to include <algorithm>, along with everything else,
> in the GMF of our named module, so that the includes inside the module
> become no-ops. But we could easily miss such an include.

I see. I don't know if it's the same thing, but this looks similar to
what happens when you mix imports and includes for the standard
library, at least in MSVC. I know it's not supposed to be like this,
but it is (at least now).

I wonder whether there is an (automated) way to check for these, as
it's definitely error-prone. My guess is that once export using works
well, we can replace what I'm writing by export using (so we gain
resilience), while keeping all the conditional includes I've
introduced (to reduce overhead). So it wouldn't be wasted work, after
all.

>
> This would also apply to Boost libraries that aren't modules, such as Config.
>
> This problem seems to make modules an all or nothing proposition. If one
> Boost library is a module, everything else also must be. We can't really mix
> and match modules and includes on a per-library basis as I envisaged. And
> things would be simplified considerably if we can also extend this to the
> standard library. It's either both import boost.* and import std, or neither.

What I've written until now assumes exactly this. It may be a lot to
assume, but if you do need to mix, you can just use headers. I may be
completely wrong, and mixing includes and imports will become
important in the future. It felt fair to make this assumption (at
least now) because the standard library seems to do it, too.

>
> > It looks like `export import <boost/foo.hpp>;` could be done easily by users (if
> > it worked).
>
> At the source level yes, but not on the CMake level.
>
> > At the minute, `export using` has problems:
> > 1) It doesn't work properly under MSVC because of an apparent language bug
> > regarding specializations [2] [3].
> > 2) It ends up placing *a lot* of declarations in the global module fragment.
> > clang docs suggest to avoid this [1], and I recall someone on the ML argued in
> > this direction, too, but I can't find the relevant message.
>
> IIUC, this is still better for performance than mixing named modules and
> includes, even if the extern "C++" trick is used to avoid the ODR violations.
> And I'm not sure that we can realistically avoid mixing imports and includes.
>
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk