Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@
/.emacs.d/elpa/
/.emacs.d/custom.el
*.deps

# specgen writes one *.root.tex per document, holding the exposition-only
# helpers that sit outside every clause. The draft states those inline in the
# clause that uses them, so they are not part of this paper's wording and are
# not committed -- see papers/wording/README.md.
papers/wording/fragments/*.root.tex
80 changes: 79 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,87 @@ env:
$(foreach v, $(.VARIABLES), $(info $(v) = $($(v))))

.PHONY: papers
papers:
papers: wording
$(MAKE) -C papers papers

# ---- Generated [expected] wording ------------------------------------------
#
# The three annotated headers are one specgen document each and one paper: a
# single invocation renders them together, so --validate sees the paper-wide
# union of documented names and a name specified by a sibling header is not
# foreign.
#
# specgen writes the fragments; this makefile assembles expected.tex from them,
# because the paper's clause order is not the headers' declaration order and
# cannot be. bad_expected_access<void> is the base class of
# bad_expected_access<E>, so the header has to define it first, while the draft
# states the primary template first. $(WORDING_CLAUSES) is where that one
# divergence is written down.

SPECGEN ?= specgen

WORDING_HEADERS := $(addprefix include/beman/expected/, \
unexpected.hpp bad_expected_access.hpp expected.hpp)

# In the draft's clause order, by stable name. These are the fragments that
# become expected.tex; specgen also writes one *.root.tex per document, holding
# the exposition-only helpers that sit outside every clause. The draft states
# those inline in the clause that uses them -- reinit-expected inside
# [expected.object.assign]'s own intro -- so they are deliberately not part of
# the assembled wording.
WORDING_CLAUSES := \
expected.unexpected \
expected.bad \
expected.bad.void \
expected.expected \
expected.void \
expected.ref

WORDING_DIR := papers/wording
WORDING_FRAGMENTS := \
$(addprefix $(WORDING_DIR)/fragments/,$(addsuffix .tex,$(WORDING_CLAUSES)))

SPECGEN_CLANG_ARGS := -std=c++2c -Iinclude
ifneq ($(SPECGEN_GCC_TOOLCHAIN),)
SPECGEN_CLANG_ARGS += --gcc-toolchain=$(SPECGEN_GCC_TOOLCHAIN)
endif

# A grouped target (GNU Make 4.3+): one invocation writes all of these, and
# make must not run it once per fragment.
$(WORDING_FRAGMENTS) &: $(WORDING_HEADERS)
@mkdir -p papers/.deps
$(SPECGEN) generate $(WORDING_HEADERS) \
--backend latex --validate --base-section-depth 2 \
--split $(WORDING_DIR)/fragments \
--root expected.unexpected.root \
--root expected.bad.root \
--root expected.root \
--depfile papers/.deps/wording.d \
$(addprefix --dep-target ,$(WORDING_FRAGMENTS)) \
--no-compile-commands -- $(SPECGEN_CLANG_ARGS)

# Assembled into a temporary first: a half-written expected.tex that make
# believes is finished is worse than no expected.tex at all.
$(WORDING_DIR)/expected.tex: $(WORDING_DIR)/preamble.tex $(WORDING_FRAGMENTS)
@cat $(WORDING_DIR)/preamble.tex > $@.tmp
@for clause in $(WORDING_CLAUSES); do \
printf '\n' >> $@.tmp; \
cat $(WORDING_DIR)/fragments/$$clause.tex >> $@.tmp; \
done
@mv $@.tmp $@
@echo "Wrote $@"

.PHONY: wording
wording: $(WORDING_DIR)/expected.tex ## Regenerate papers/wording/ from the annotated headers via specgen

# What specgen read to produce the fragments -- including headers reached only
# through an #include, which is the edge a hand-written prerequisite list
# forgets. Written by --depfile above; absent until the first run, hence
# $(wildcard): a bare glob that matches nothing stays a literal target name,
# and .DEFAULT below would hand it to cmake. Named, not globbed: papers/.deps/
# is also latexmk's -deps-out directory, and its paths are relative to papers/.
-include $(wildcard papers/.deps/wording.d)

.DEFAULT: $(_build_path)/CMakeCache.txt ## Other targets passed through to cmake
$(CMAKE) --build $(_build_path) --config $(CONFIG) --target $@ -- -k 0

Expand Down
16 changes: 16 additions & 0 deletions include/beman/expected/bad_expected_access.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace expected {
template <class E>
class bad_expected_access;

// \rSec2[expected.bad.void]{Class template specialization bad_expected_access<void>}
template <>
class bad_expected_access<void> : public std::exception {
protected:
Expand All @@ -74,6 +75,11 @@ class bad_expected_access<void> : public std::exception {
BEMAN_EXPECTED_CONSTEXPR_EXCEPTION const char* what() const noexcept override;
};

// \rSec2[expected.bad]{Class template bad_expected_access}
//! \remarks The class template `bad_expected_access` defines the type of
//! objects thrown as exceptions to report the situation where an attempt is
//! made to access the value of an `expected<T, E>` object for which
//! `has_value()` is `false`.
template <class E>
class bad_expected_access : public bad_expected_access<void> {
public:
Expand All @@ -85,40 +91,50 @@ class bad_expected_access : public bad_expected_access<void> {
constexpr const E&& error() const&& noexcept;

private:
//! \expos
E unex;
};

// bad_expected_access<void> out-of-line definitions

//! \returns An implementation-defined ntbs, which during constant evaluation
//! is encoded with the ordinary literal encoding (\iref{lex.ccon}).
inline BEMAN_EXPECTED_CONSTEXPR_EXCEPTION const char* bad_expected_access<void>::what() const noexcept {
return "bad expected access";
}

// bad_expected_access<E> out-of-line definitions

//! \effects Initializes `unex` with `std::move(e)`.
template <class E>
BEMAN_EXPECTED_CONSTEXPR_EXCEPTION bad_expected_access<E>::bad_expected_access(E e) : unex(std::move(e)) {}

//! \returns An implementation-defined ntbs, which during constant evaluation
//! is encoded with the ordinary literal encoding (\iref{lex.ccon}).
template <class E>
BEMAN_EXPECTED_CONSTEXPR_EXCEPTION const char* bad_expected_access<E>::what() const noexcept {
return "bad expected access";
}

//! \returns `unex`.
template <class E>
constexpr E& bad_expected_access<E>::error() & noexcept {
return unex;
}

//! \returns `unex`.
template <class E>
constexpr const E& bad_expected_access<E>::error() const& noexcept {
return unex;
}

//! \returns `std::move(unex)`.
template <class E>
constexpr E&& bad_expected_access<E>::error() && noexcept {
return std::move(unex);
}

//! \returns `std::move(unex)`.
template <class E>
constexpr const E&& bad_expected_access<E>::error() const&& noexcept {
return std::move(unex);
Expand Down
Loading
Loading