API — ICoreEssentials/UI/Text
The public contract of 7 header(s) under ICoreEssentials/UI/Text — 7 class/struct definition(s), 77 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
| Header | Defines | Declarations | Bases |
|---|---|---|---|
ICoreSyntaxHighlighter.h | ICoreSyntaxHighlighter | 11 | — |
ICoreSyntaxHighlighterBase.h | ICoreSyntaxHighlighterBase | 12 | public ICoreSyntaxHighlighter |
ICoreTextBlock.h | ICoreTextBlock | 14 | — |
ICoreTextCharFormat.h | ICoreTextCharFormat | 15 | — |
ICoreTextCursor.h | ICoreTextCursor | 20 | — |
ICoreTextDecoration.h | ICoreTextDecoration | 0 | — |
ICoreTextDocumentHandle.h | ICoreTextDocumentHandle | 5 | — |
ICoreSyntaxHighlighter.h#
ICoreEssentials/UI/Text/ICoreSyntaxHighlighter.h
ICoreSyntaxHighlighter#
ICoreSyntaxHighlighter.h:39 · class · pImpl · 11 declaration(s)
The highlighter seam: what a syntax highlighter needs from whatever is actually laying the text out.
class ICoreSyntaxHighlighter {
public:
virtual ~ICoreSyntaxHighlighter();
ICoreSyntaxHighlighter(const ICoreSyntaxHighlighter&) = delete;
ICoreSyntaxHighlighter& operator=(const ICoreSyntaxHighlighter&) = delete;
// Re-run every paragraph. Public because a caller outside the hierarchy
// asks for it after a theme change.
void rehighlight();
protected:
// The editors mint the handle (`documentHandle()`), so a subclass's
// constructor line names no toolkit at all -- which has been true since
// E6.1 and is what makes this conversion invisible to them.
explicit ICoreSyntaxHighlighter(const ICoreTextDocumentHandle& document);
// ⚠ THE ONE THING A SUBCLASS MUST IMPLEMENT, and the layout of the whole
// seam follows from it: the toolkit calls US per paragraph, we call this.
// Pure, so a highlighter that forgets it does not compile.
//
// ⚠ IT MUST NOT BE CALLED WHILE A CONSTRUCTOR IS STILL RUNNING. The Qt
// seat's own note records what that cost: an immediate theme callback ran
// `rehighlight()` from the base constructor, which dispatched straight into
// a still-pure `highlightBlock` and aborted the process on
// `__cxa_pure_virtual` the moment any code editor was built. Both seats
// therefore attach the document but do NOT rehighlight during construction.
virtual void highlightBlock(const ICoreString& text) = 0;
public:
// ⚠ PUBLIC, NOT PROTECTED, AND THE GUARD IS WHAT SAID SO. These five are
// what a highlighter CALLS while it works, not what it overrides -- and the
// header surface rule bans protected non-virtual helpers precisely because
// a thing called from a subclass is public API written down as an
// inheritance detail. `check_header_surface.py` failed this header with 5
// violations on its first draft.
//
// ⚠⚠ AND BOTH NEIGHBOURS HAD ALREADY BEEN CORRECTED FOR EXACTLY THIS.
// `ICoreSyntaxHighlighterBase` made its rule engine public at H4.45 with
// the same sentence, and `ICoreAppKitSyntaxHighlighter`'s run surface
// carries it too ("PUBLIC, NOT PROTECTED, AND THAT IS DELIBERATE"). I
// reproduced the mistake between two headers that already state the answer,
// which is what a guard is for. Making them virtual to claim exemption 2
// would buy the guard's silence with vtable entries nobody wants.
// Paint a run of the paragraph being highlighted. `start` is relative to
// that paragraph, not to the document.
void setFormat(int start, int count, const ICoreTextCharFormat& format);
// The format the run already carries. A distinct NAME rather than an
// overload of setFormat: the two differ only in return type, which
// overloading cannot express.
[[nodiscard]] ICoreTextCharFormat charFormatAt(int position) const;
// The block-state machine, which is what lets a construct span paragraphs.
// Three of the thirteen subclasses use it, all for block comments: set 1 at
// the end of a paragraph that leaves a comment open, and read it from the
// next paragraph.
[[nodiscard]] int previousBlockState() const;
[[nodiscard]] int currentBlockState() const;
void setCurrentBlockState(int state);
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreSyntaxHighlighterBase.h#
ICoreEssentials/UI/Text/ICoreSyntaxHighlighterBase.h
ICoreSyntaxHighlighterBase#
ICoreSyntaxHighlighterBase.h:36 · class · bases public ICoreSyntaxHighlighter · pImpl · 12 declaration(s)
ICoreSyntaxHighlighterBase - owns ALL styling (single source of truth) - provides rule engine THIS IS THE PROJECT'S SYNTAX HIGHLIGHTER COMPONENT (task C9).
class ICoreSyntaxHighlighterBase : public ICoreSyntaxHighlighter {
public:
// E6.1's ctor: the editors mint the handle (documentHandle()), so a
// subclass's constructor line names zero Qt.
explicit ICoreSyntaxHighlighterBase(const ICoreTextDocumentHandle& document);
// ⚠ THE `QTextDocument*` MIGRATION CTOR IS GONE (A5.2). F4b's job was to
// retire its callers file by file, and it finished: measured before
// removal, ALL THIRTEEN language highlighters construct with the handle
// above and not one names the toolkit form. A migration constructor with
// no migrating callers left is a Qt type in a public header serving
// nobody.
// Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
// be instantiated in this header. There was no user-declared destructor
// before H4.45 -- the implicit one was fine while every member was a
// complete type.
~ICoreSyntaxHighlighterBase() override;
// =========================
// THE RULE ENGINE -- PUBLIC SINCE H4.45
// =========================
//
// ⚠ THIS SURFACE WAS `protected:`, AND MAKING IT PUBLIC IS THE ROW RATHER
// THAN A SIDE EFFECT OF IT. The engine and the palette were protected DATA
// and protected NON-VIRTUAL helpers; the header surface rule bans both and
// exemption 2 does not reach them, since it covers protected VIRTUAL
// declarations only. Nine language highlighters in src/ICoreSDK drive this
// engine across a module boundary -- so what it is, is public API that had
// been written down as an inheritance detail. It is spelled that way now.
//
// Not made virtual to claim exemption 2: these are CALLED, not overridden,
// and adding vtable entries to buy the guard's silence is the abuse the
// guidelines warn about.
// The token classes this engine paints. A subclass names the CLASS, never
// the colour: the base owns the format each token wears and re-derives all
// thirteen from the theme on every switch (initTheme), so a highlighter
// cannot go stale holding a colour of its own.
enum class Token {
Keyword, Type, String, Char, Comment, Number, Function,
Class, Macro, Attribute, Operator, Lifetime, Builtin
};
// Register a pattern. Replaces `rules.push_back({pattern, fmtX})`, which is
// what all 40 external uses of the old `rules` member were -- one shape.
void addRule(const ICoreRegex& pattern, Token token);
// For a subclass with a format of its own (ICoreScriptEditorHighlighter's
// fmtHandle / fmtPort / fmtSymbol) rather than one of the thirteen.
void addRule(const ICoreRegex& pattern, const ICoreTextCharFormat& format);
void clearRules();
// The format `token` wears under the active theme. NOT named format(): that
// would hide the inherited QSyntaxHighlighter::format(int) behind an
// overload nobody asked for -- the overload-hiding trap this tier has paid
// for before. charFormatAt() remains the way to read a run's own format.
[[nodiscard]] ICoreTextCharFormat tokenFormat(Token token) const;
void applyRules(const ICoreString& text);
void applyRegex(const ICoreString& text,
const ICoreRegex& re,
const ICoreTextCharFormat& fmt);
void applyRegex(const ICoreString& text, const ICoreRegex& re, Token token);
// E6.1: the ICore-typed run surface. Declaring setFormat here HIDES the
// inherited Qt overloads, so the `using` re-exposes them for the
// still-unflipped subclasses (F4b walks them off it); resolution is
// unambiguous both ways because an exact match outranks the cushion
// conversion in either direction. charFormatAt is a distinct name, not an
// overload of Qt's format(int): the two differ only in return type, which
// overloading cannot express.
// ⚠ The `using ICoreSyntaxHighlighter::setFormat;` cushion that stood here
// is GONE with the Qt base it re-exposed: there are no inherited toolkit
// overloads left to hide, so the two declarations below are the whole
// overload set. (F4b walked the last subclass off the toolkit spelling.)
void setFormat(int start, int count, const ICoreTextCharFormat& format);
void setFormat(int start, int count, Token token);
[[nodiscard]] ICoreTextCharFormat charFormatAt(int position) const;
protected:
// ⚠ THE `highlightBlock(const QString&) final` FORWARDER THAT STOOD HERE
// MOVED INTO THE SEAM'S BACKEND Impl (A5.2). It was the toolkit's entry
// point, taken over once for the whole hierarchy so the thirteen
// subclasses could speak ICoreString -- and taking it over is exactly what
// made those thirteen ordinary migratable code, which is the finding this
// note used to carry and which still stands:
//
// Twenty-six of the forty remaining QString occurrences in the tree were
// `highlightBlock(const QString&)` -- thirteen declarations and thirteen
// definitions -- and every one had been classified "permanent, because Qt
// declares the signature". What that classification could not see is that
// "permanent" means "permanent WHILE QT DECLARES IT". Interposing one
// override made the signature this project's.
//
// A5.2 finishes the same move one layer down: with the seam a pImpl, the
// toolkit does not declare the signature at all any more, and the
// forwarder belongs to whichever backend has a toolkit to forward from.
// ⚠ `virtual void highlightBlock(const ICoreString&) = 0;` IS NOT
// RE-DECLARED HERE ANY MORE (A5.2). It belongs to the seam now, and
// repeating it made the compiler right to warn: a re-declaration of an
// inherited pure virtual is `override` whether or not it says so
// (-Winconsistent-missing-override caught it). The declaration that
// survived was the seam's, which is where the toolkit's entry point calls
// it from -- so the thirteen subclasses still override exactly the name
// they always did, one layer further down.
// E6.1: the ICore-typed run surface. Declaring setFormat here HIDES the
// inherited Qt overloads, so the `using` re-exposes them for the
// still-unflipped subclasses (F4b walks them off it); resolution is
// unambiguous both ways because an exact match outranks the cushion
// conversion in either direction. charFormatAt is a distinct name, not an
// overload of Qt's format(int): the two differ only in return type, which
// overloading cannot express. It hands back the FULL format the run
// already carries (see ICoreTextCharFormat.h on merge fidelity).
// setCurrentBlockState/previousBlockState need no forwarders: their
// signatures are int-only, so an unqualified call names zero Qt already.
// Re-reads every character format from the syntax tokens. Virtual so a
// subclass with formats of its own refreshes those in the same pass -- the
// base constructor subscribes this to themeChanged, and a format that is
// not refreshed there keeps the previous theme's colour.
virtual void initTheme();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreTextBlock.h#
ICoreEssentials/UI/Text/ICoreTextBlock.h
⚠ THE INBOUND QT CONVERSION IS NOT A CONSTRUCTOR ANY MORE (A9.23, 2026-08-24), so this header names no Qt type and the forward declaration that stood here is gone. It is
icoreFromQt(const QTextBlock&)in UI/Backends/Qt/Values/ICoreValuesQt.h, which builds one through nativeStorageMut() -- the inbound half of thevoid*seam idiom, and the reason that accessor is declared below.
ICoreTextBlock#
ICoreTextBlock.h:26 · class · 14 declaration(s)
One paragraph/line of a text document, as a value handle.
class ICoreTextBlock {
public:
// An invalid block -- isValid() false, like walking past the last one.
ICoreTextBlock();
// Wrapper-zone inbound seam (the editors and icoreQt() build these).
ICoreTextBlock(const ICoreTextBlock& other);
ICoreTextBlock(ICoreTextBlock&& other) noexcept;
ICoreTextBlock& operator=(const ICoreTextBlock& other);
ICoreTextBlock& operator=(ICoreTextBlock&& other) noexcept;
~ICoreTextBlock();
[[nodiscard]] bool isValid() const;
[[nodiscard]] bool isVisible() const;
[[nodiscard]] int blockNumber() const;
// First character's position in the whole document.
[[nodiscard]] int position() const;
[[nodiscard]] ICoreString text() const;
// The following block; invalid past the last one, so the gutter's loop is
// `for (auto b = firstBlock(); b.isValid(); b = b.next())`.
[[nodiscard]] ICoreTextBlock next() const;
// The seam, per §1. Call icoreQt() from a .cpp rather than reaching in.
//
// ⚠ OUT OF LINE SINCE H4.4x. icoreQt() is inline and calls this, so every
// unwrap at a paint site is now a call into the library instead of a field
// read. That cost was priced and accepted for every non-template type at
// the guidelines (2026-08-14) -- do not re-litigate it here.
[[nodiscard]] const void* nativeStorage() const;
// The MUTABLE half (A9.23). Its one purpose is the INBOUND direction that
// used to be a constructor naming a toolkit type: a dropped-zone seam
// builds a default value and assigns the native object into this buffer.
// ICorePixmap.h's pair is the precedent and its warning applies -- call
// icoreFromQt() from a .cpp rather than reaching in here.
void* nativeStorageMut();
// Public only so the .cpp can pin them. Measured, not assumed:
// QTextBlock is {QTextDocumentPrivate*, int} -- 16 bytes / align 8 on
// this tree's Qt 6.10.2, macOS arm64. Non-polymorphic.
static constexpr std::size_t kNativeStorageSize = 16;
static constexpr std::size_t kNativeStorageAlign = 8;
};
ICoreTextCharFormat.h#
ICoreEssentials/UI/Text/ICoreTextCharFormat.h
⚠ THE INBOUND QT CONVERSION IS NOT A CONSTRUCTOR ANY MORE (A9.23, 2026-08-24), so this header names no Qt type and the forward declaration that stood here is gone. It is
icoreFromQt(const QTextCharFormat&)in UI/Backends/Qt/Values/ICoreValuesQt.h, which builds one through nativeStorageMut() -- the inbound half of thevoid*seam idiom, and the reason that accessor is declared below.
ICoreTextCharFormat#
ICoreTextCharFormat.h:31 · class · 15 declaration(s)
A character-run format: what a syntax highlighter paints a token with.
class ICoreTextCharFormat {
public:
ICoreTextCharFormat();
void setForeground(const ICoreColor& color);
void setBold(bool bold);
void setItalic(bool italic);
void setUnderlineStyle(ICoreTextUnderlineStyle style);
void setUnderlineColor(const ICoreColor& color);
// Implicit on purpose — the migration cushion, ICoreIcon's QIcon shape:
// an unflipped highlighter's QTextCharFormat still flows into
// applyRegex/setFormat while F4b walks the 38 files. Wrapper zone only;
// a Studio file naming QTextCharFormat is exactly what F4b removes.
ICoreTextCharFormat(const ICoreTextCharFormat& other);
ICoreTextCharFormat(ICoreTextCharFormat&& other) noexcept;
ICoreTextCharFormat& operator=(const ICoreTextCharFormat& other);
ICoreTextCharFormat& operator=(ICoreTextCharFormat&& other) noexcept;
~ICoreTextCharFormat();
// VALUE EQUALITY -- added for W5.2. (The board file that row lives on is
// named in the .cpp, not here: gen_api.py lifts this comment onto a PUBLIC
// api page, where a board filename trips D15 audience-leak.)
//
// ⚠ This is not a convenience. Without it there is NO backend-neutral way
// to ask whether two formats are the same, because the only other handle
// on the value is nativeStorage(), and comparing those bytes compares the
// toolkit's SHARED-DATA POINTER rather than the format -- two formats with
// identical colour, weight and underline compare unequal. A conformance
// suite for the syntax-highlighter seat (the thing that says whether the
// WinUI seat is correct) cannot be written in ICore types until this
// exists, so it is part of the seat contract rather than an extra.
//
// Each backend compares with its own toolkit's format equality; the
// SEMANTICS this surface promises are value equality, not identity.
[[nodiscard]] bool operator==(const ICoreTextCharFormat& other) const;
[[nodiscard]] bool operator!=(const ICoreTextCharFormat& other) const;
// The seam, per §1. Call icoreQt() from a .cpp rather than reaching in.
//
// ⚠ OUT OF LINE SINCE H4.4x. icoreQt() is inline and calls this, so every
// unwrap at a paint site is now a call into the library instead of a field
// read. That cost was priced and accepted for every non-template type at
// the guidelines (2026-08-14) -- do not re-litigate it here.
[[nodiscard]] const void* nativeStorage() const;
// The MUTABLE half (A9.23). Its one purpose is the INBOUND direction that
// used to be a constructor naming a toolkit type: a dropped-zone seam
// builds a default value and assigns the native object into this buffer.
// ICorePixmap.h's pair is the precedent and its warning applies -- call
// icoreFromQt() from a .cpp rather than reaching in here.
void* nativeStorageMut();
// Public only so the .cpp can pin them. Measured, not assumed:
// QTextCharFormat is QTextFormat's {QSharedDataPointer, qint32} — 16
// bytes / align 8 on this tree's Qt 6.10.2, macOS arm64. Non-polymorphic.
static constexpr std::size_t kNativeStorageSize = 16;
static constexpr std::size_t kNativeStorageAlign = 8;
};
File-scope declarations#
// How an underlined run is drawn. Mapped to the toolkit by a switch in the
// .cpp, so the numeric values here are this project's own — nothing to pin.
enum class ICoreTextUnderlineStyle {
None,
Wave, // the "won't run" squiggle
};
ICoreTextCursor.h#
ICoreEssentials/UI/Text/ICoreTextCursor.h
⚠ THE INBOUND QT CONVERSION IS NOT A CONSTRUCTOR ANY MORE (A9.23, 2026-08-24), so this header names no Qt type and the forward declaration that stood here is gone. It is
icoreFromQt(const QTextCursor&)in UI/Backends/Qt/Values/ICoreValuesQt.h, which builds one through nativeStorageMut() -- the inbound half of thevoid*seam idiom, and the reason that accessor is declared below.
ICoreTextCursor#
ICoreTextCursor.h:29 · class · 20 declaration(s)
An editing position in a text document, as a value handle.
class ICoreTextCursor {
public:
// A null cursor.
ICoreTextCursor();
// A cursor at the start of the editor's document.
explicit ICoreTextCursor(const ICoreTextDocumentHandle& document);
// Wrapper-zone inbound seam (the editors and icoreQt() build these).
ICoreTextCursor(const ICoreTextCursor& other);
ICoreTextCursor(ICoreTextCursor&& other) noexcept;
ICoreTextCursor& operator=(const ICoreTextCursor& other);
ICoreTextCursor& operator=(ICoreTextCursor&& other) noexcept;
~ICoreTextCursor();
// Absolute position in the document.
[[nodiscard]] int position() const;
enum class MoveMode {
Move, // move the anchor with the position (no selection)
KeepAnchor, // leave the anchor: the span in between is selected
};
void setPosition(int position, MoveMode mode = MoveMode::Move);
// The other end of the selection: equal to position() when nothing is
// selected. The selection is [selectionStart(), selectionEnd()) whichever
// way it was made.
[[nodiscard]] int anchor() const;
[[nodiscard]] bool hasSelection() const;
[[nodiscard]] int selectionStart() const;
[[nodiscard]] int selectionEnd() const;
[[nodiscard]] ICoreTextBlock block() const;
// Position relative to the start of the caret's block/line.
[[nodiscard]] int positionInBlock() const;
// Replaces the selection if there is one, as the toolkit does.
void insertText(const ICoreString& text);
void selectDocument();
// The one block-format the script editor needs: proportional line height,
// in percent of the font's natural height, MERGED so the blocks keep
// their other properties. 100 is the natural height.
void mergeLineHeightPercent(int percent);
// The seam, per §1. Call icoreQt() from a .cpp rather than reaching in.
//
// ⚠ OUT OF LINE SINCE H4.4x. icoreQt() is inline and calls this, so every
// unwrap at a paint site is now a call into the library instead of a field
// read. That cost was priced and accepted for every non-template type at
// the guidelines (2026-08-14) -- do not re-litigate it here.
[[nodiscard]] const void* nativeStorage() const;
// The MUTABLE half (A9.23). Its one purpose is the INBOUND direction that
// used to be a constructor naming a toolkit type: a dropped-zone seam
// builds a default value and assigns the native object into this buffer.
// ICorePixmap.h's pair is the precedent and its warning applies -- call
// icoreFromQt() from a .cpp rather than reaching in here.
void* nativeStorageMut();
// Public only so the .cpp can pin them. Measured, not assumed:
// QTextCursor is one shared-data pointer -- 8 bytes / align 8 on this
// tree's Qt 6.10.2, macOS arm64. Non-polymorphic.
static constexpr std::size_t kNativeStorageSize = 8;
static constexpr std::size_t kNativeStorageAlign = 8;
};
ICoreTextDecoration.h#
ICoreEssentials/UI/Text/ICoreTextDecoration.h
ICoreTextDecoration#
ICoreTextDecoration.h:14 · struct · 0 declaration(s)
A mark drawn over a range of a text pane's document, independent of any syntax highlighter: a find match, a matching bracket, the debugger's current line, a runtime error's squiggle.
struct ICoreTextDecoration {
public:
enum class Style {
Background, // a fill under the glyphs
Box, // a 1px outline round the range
Underline, // a straight line under the glyphs
WavyUnderline, // a squiggle under the glyphs
LineBackground // the whole row of every line the range touches, edge to edge
};
int from = 0;
int to = 0;
Style style = Style::Background;
ICoreColor colour;
// The owner's own number for this mark (an index into its diagnostics,
// say), handed back by ICoreRichTextEdit::decorationsAt. Not drawn.
int tag = 0;
};
};
ICoreTextDocumentHandle.h#
ICoreEssentials/UI/Text/ICoreTextDocumentHandle.h
⚠ NO
class QTextDocument;HERE ANY MORE (A9.23, 2026-08-24) -- see the two members below that used to need it. The typed conversions areicoreQt()/icoreTextDocumentHandle()in UI/Backends/Qt/ICoreNativeHandleAccess.h.
ICoreTextDocumentHandle#
ICoreTextDocumentHandle.h:27 · class · 5 declaration(s)
An opaque pass-through: the document an editor owns, on its way to the syntax highlighter that will watch it.
class ICoreTextDocumentHandle {
public:
ICoreTextDocumentHandle();
// Wrapper-zone side: the editors construct one from their Impl's document,
// as an opaque address. ⚠ THIS TOOK A `QTextDocument*` UNTIL 2026-08-24
// (A9.23) and that is what put a Qt name on this class's contract. Same
// pointer, same non-owning contract; only the type is gone, and the two
// call sites are both inside UI/Backends/Qt/.
explicit ICoreTextDocumentHandle(ICoreNativeHandle document);
[[nodiscard]] bool isNull() const;
// The backend-neutral seam, and the reason it had to be added: `qt()` was
// this class's ONLY accessor, and it named a Qt type. A non-Qt backend
// could neither define it nor read the document out of a handle it was
// handed, so the whole text tier was unreachable from any other backend.
//
// ⚠ SINCE 2026-08-24 IT IS THE ONLY ACCESSOR AGAIN, THE OTHER WAY ROUND
// (A9.23): `qt()` is gone and `icoreQt(handle)` in the Qt backend zone
// casts what this returns. The AppKit and WinUI seats each carried a
// banner saying `qt()` was declared here and left undefined on their
// backend; both statements retire with it.
//
// ⚠ THIS IS THE SHAPE EVERY OTHER OPAQUE-STORAGE WRAPPER IN THE TREE
// ALREADY HAS -- ICoreColor, ICoreFont, ICorePixmap, ICoreCursor,
// ICoreKeySequence, ICorePen, ICoreBrush and ICorePainterPath all publish
// `const void* nativeStorage() const`. This class was the exception, and
// the exception was invisible while there was only one backend.
//
// ⚠ A REGISTRY WOULD NOT HAVE WORKED HERE, which is why this is a surface
// change rather than a backend trick: ICorePrinter could publish its state
// into a map keyed by its own address because it is NON-COPYABLE
// (§0.32), and this class is a trivially-copyable value that is passed by
// value and copied freely. There is no stable key.
//
// Additive: no existing caller changes, and the Qt seat gains a one-line
// definition. Call icoreQt() from a .cpp rather than reaching in here.
[[nodiscard]] const void* nativeStorage() const;
// Public only so the .cpp can pin them. A pointer, measured rather than
// assumed, like every other buffer in this tier.
static constexpr std::size_t kNativeStorageSize = sizeof(void*);
static constexpr std::size_t kNativeStorageAlign = alignof(void*);
};