-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsmallstring.cppm
More file actions
56 lines (49 loc) · 2.97 KB
/
Copy pathsmallstring.cppm
File metadata and controls
56 lines (49 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Module interface for smallstring.
//
// The header is the single source of truth; this unit only attaches its declarations to module
// `smallstring`. See the note at the top of include/smallstring.hpp for the ownership rule.
module;
// smallstring deliberately calls Assert(), not assert(), so the consumer can substitute its own
// assertion. Textually that was done by #define-ing Assert before including the header. Modules take
// that away: the header is an `import` at the consumer, and its macros are baked in *here*, when the
// interface is compiled. So the hook has to live here.
//
// Point SMALLSTRING_PRELUDE at a header that #define-s Assert (and includes whatever that needs).
// Without it, smallstring.hpp falls back to plain assert() as before.
#ifdef SMALLSTRING_PRELUDE
#include SMALLSTRING_PRELUDE
#endif
// And that fallback needs <cassert> -- which is why this include is here rather than in the header.
//
// smallstring.hpp does include <cassert>, but only on its textual path: the module-interface path skips
// the whole include block, and it has to, because it is read from inside an `export { }` block where a
// first-time #include is not allowed. Its `#ifndef Assert` fallback still expands to assert(), though,
// so with no SMALLSTRING_PRELUDE to define Assert the interface would not compile -- "use of undeclared
// identifier 'assert'", once per call site. `import std.compat` cannot rescue it either: assert is a
// macro, and macros do not cross a module boundary.
//
// So the fallback's dependency belongs here, next to the hook it backs. It is a macro, expanded while
// this unit is preprocessed, so nothing about it reaches importers; <cassert> is just <assert.h>, and
// carries none of the libstdc++ declarations the note below is about.
#include <cassert>
// std comes in as `import std.compat` below, NOT as textual libstdc++ headers here.
//
// Textual <stdexcept> in this fragment would bake libstdc++'s <string> declarations into the BMI as
// global-module entities. Any consumer that then reads <string> textually -- directly, or through
// <fmt/format.h> -- re-declares basic_string.tcc's explicit instantiations on top of them and clang
// rejects it: "explicit instantiation of 'getline' does not refer to a function template". It reaches
// consumers that never name smallstring, too, because a module that imports smallstring carries those
// declarations onward in its own BMI.
#include <sys/types.h>
// fmt is textual, here and everywhere else in smallstring -- the header we are about to read
// specialises fmt::formatter, and it is the one heavy header that has to stay in this fragment. The
// note at the top of include/smallstring.hpp explains why it is never an `import fmt;`, and asserts
// the FMT_ATTACH_TO_GLOBAL_MODULE that lets a textual read here meet an imported fmt elsewhere.
#include <fmt/format.h>
export module smallstring;
import std.compat;
#define SMALLSTRING_MODULE_INTERFACE 1
export {
#include "smallstring.hpp"
}
#undef SMALLSTRING_MODULE_INTERFACE