24 template<
class T> T*
as() { assert(
isa<T>());
return static_cast<T*
>(
this); }
31 return static_cast<B*
>(
this)->node() == T::Node ?
static_cast<T*
>(
this) :
nullptr;
33 return dynamic_cast<T*
>(
static_cast<B*
>(
this));
45 template<
class T,
class... Args>
46 T*
expect(std::format_string<Args...> fmt, Args&&... args) {
47 if (
auto res =
isa<T>())
return res;
48 auto what = std::format(fmt, std::forward<Args>(args)...);
49 if constexpr (std::formattable<const B*, char>)
50 throwf(
"expected {}, but got '{}'", what,
static_cast<const B*
>(
this));
52 throwf(
"expected {}", what);
56 template<
class T,
class... Args>
57 const T*
expect(std::format_string<Args...> fmt, Args&&... args)
const {
Inherit from this class using CRTP, for some nice dynamic_cast-style wrappers.
T * as()
static_cast with debug check.
const T * expect(std::format_string< Args... > fmt, Args &&... args) const
const version.
const T * isa() const
const version.
T * expect(std::format_string< Args... > fmt, Args &&... args)
Like as() but - instead of merely asserting via isa() in Debug builds - throws a std::logic_error wit...
const T * as() const
const version.
void throwf(std::format_string< Args... > fmt, Args &&... args)
Throws a T (a std::logic_error by default) whose message is std::format(fmt, args....