#pragma once
#include <type_traits>
#include <utility>
// Uses dynamic dispatch to permit lazy OR eager argument evaluation at the
// caller's discretion, with uniform access to the final value from the callee's
// perspective.
template <typename VAL_TYPE>
class LazyType_Base
{
protected:
// For LazyType_TrueLazy
template <typename CALLABLE>
LazyType_Base(CALLABLE&& expr)
{
static_assert(
std::is_same<
typename std::remove_reference<decltype(expr())>::type, VAL_TYPE
>::value,
"Expression does not evaluate to correct type!");
}
// For LazyType_Eager
// =default is not permitted by GCC here; see
// httphttps://stackoverflow.com/q/38213809/1858225
LazyType_Base(void) {}
public:
// Both compilers suddenly fail when this is introduced, attempting to
// instantiate `LazyType_Base<LazyType_Base<VAL_TYPE>>`, which makes no
// sense. See httphttps://stackoverflow.com/q/38214138/1858225
// In general, not making the destructor virtual *should* be safe as long as
// users are just using this type as it's intended (i.e. for lazy arguments
// to functions, to be used immediately or discarded without passing
// pointers around for deletion later).
// virtual ~LazyType_Base(void) =default;
virtual operator VAL_TYPE(void) =0;
};
// Takes an arbitrary expression and creates a class that will evaluate the
// expression when necessary.
template <typename VAL_TYPE, typename CALLABLE>
class LazyType_TrueLazy : public LazyType_Base<VAL_TYPE>
{
// friend LazyType_TrueLazy<VAL_TYPE, CALLABLE> MakeLazy<CALLABLE>(CALLABLE&& expr);
// With a working friend declaration, make all constructors private; `protect`
// default constructors in `LazyType_Base`
public:
LazyType_TrueLazy(CALLABLE&& expr)
: LazyType_Base<VAL_TYPE>{std::forward<CALLABLE>(expr)}
, expr_{std::forward<CALLABLE>(expr)}
{}
operator VAL_TYPE(void) override final
{
return expr_();
}
private:
CALLABLE expr_;
};
// If VAL_TYPE is the same as EXPR_TYPE, then we do not have a truly lazy
// instantiation.
template <typename VAL_TYPE>
class LazyType_Eager : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_Eager(
VAL_TYPE&& final_val)
: LazyType_Base<VAL_TYPE>{}
, val_{final_val}
{}
operator VAL_TYPE(void) override final
{
return val_;
}
private:
VAL_TYPE val_;
};
// C++14: since template `auto` arguments are not permitted prior to C++17,
// we need a helper function to evaluate the type of the callable, in case it's
// a lambda.
template <typename CALLABLE>
auto MakeLazy(CALLABLE&& expr)
{
return LazyType_TrueLazy<
typename std::remove_reference<decltype(expr())>::type, CALLABLE>{
std::forward<CALLABLE>(expr)};
}
#define LAZY_ARG(expr) \
MakeLazy([&](void)->auto { return expr; })
// Is there some way to create an implicit conversion to `LazyType_Eager` for
// all types that will be applied for any attempted conversion to
// `LazyType_Base`?
#define EAGER_ARG(val) \
LazyType_Eager<typename std::remove_reference<decltype(val)>::type>{val}
// Must provide a REFERENCE so that the actual type will not be sliced...but we
// don't actually want a mutable reference to a long-lived object, so we take an
// r-value reference. This is very simple to use with the `LAZY_ARG` and
// `EAGER_ARG` macros.
#define OPTIONALLY_LAZY(type) \
LazyType_Base<type>&&
- G++ doesn't permit use of
=default
constructor for base-class template G++ doesn't permit use of=default
constructor for base-class template - Existence of virtual destructor changes evaluation of seemingly-unrelated expression's type Existence of virtual destructor changes evaluation of seemingly-unrelated expression's type SOLVED
#pragma once
#include <type_traits>
#include <utility>
// Uses dynamic dispatch to permit lazy OR eager argument evaluation at the
// caller's discretion, with uniform access to the final value from the callee's
// perspective.
template <typename VAL_TYPE>
class LazyType_Base
{
protected:
// For LazyType_TrueLazy
template <typename CALLABLE>
LazyType_Base(CALLABLE&& expr)
{
static_assert(
std::is_same<
typename std::remove_reference<decltype(expr())>::type, VAL_TYPE
>::value,
"Expression does not evaluate to correct type!");
}
// For LazyType_Eager
// =default is not permitted by GCC here; see
// http://stackoverflow.com/q/38213809/1858225
LazyType_Base(void) {}
public:
// Both compilers suddenly fail when this is introduced, attempting to
// instantiate `LazyType_Base<LazyType_Base<VAL_TYPE>>`, which makes no
// sense. See http://stackoverflow.com/q/38214138/1858225
// In general, not making the destructor virtual *should* be safe as long as
// users are just using this type as it's intended (i.e. for lazy arguments
// to functions, to be used immediately or discarded without passing
// pointers around for deletion later).
// virtual ~LazyType_Base(void) =default;
virtual operator VAL_TYPE(void) =0;
};
// Takes an arbitrary expression and creates a class that will evaluate the
// expression when necessary.
template <typename VAL_TYPE, typename CALLABLE>
class LazyType_TrueLazy : public LazyType_Base<VAL_TYPE>
{
// friend LazyType_TrueLazy<VAL_TYPE, CALLABLE> MakeLazy<CALLABLE>(CALLABLE&& expr);
// With a working friend declaration, make all constructors private; `protect`
// default constructors in `LazyType_Base`
public:
LazyType_TrueLazy(CALLABLE&& expr)
: LazyType_Base<VAL_TYPE>{std::forward<CALLABLE>(expr)}
, expr_{std::forward<CALLABLE>(expr)}
{}
operator VAL_TYPE(void) override final
{
return expr_();
}
private:
CALLABLE expr_;
};
// If VAL_TYPE is the same as EXPR_TYPE, then we do not have a truly lazy
// instantiation.
template <typename VAL_TYPE>
class LazyType_Eager : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_Eager(
VAL_TYPE&& final_val)
: LazyType_Base<VAL_TYPE>{}
, val_{final_val}
{}
operator VAL_TYPE(void) override final
{
return val_;
}
private:
VAL_TYPE val_;
};
// C++14: since template `auto` arguments are not permitted prior to C++17,
// we need a helper function to evaluate the type of the callable, in case it's
// a lambda.
template <typename CALLABLE>
auto MakeLazy(CALLABLE&& expr)
{
return LazyType_TrueLazy<
typename std::remove_reference<decltype(expr())>::type, CALLABLE>{
std::forward<CALLABLE>(expr)};
}
#define LAZY_ARG(expr) \
MakeLazy([&](void)->auto { return expr; })
// Is there some way to create an implicit conversion to `LazyType_Eager` for
// all types that will be applied for any attempted conversion to
// `LazyType_Base`?
#define EAGER_ARG(val) \
LazyType_Eager<typename std::remove_reference<decltype(val)>::type>{val}
// Must provide a REFERENCE so that the actual type will not be sliced...but we
// don't actually want a mutable reference to a long-lived object, so we take an
// r-value reference. This is very simple to use with the `LAZY_ARG` and
// `EAGER_ARG` macros.
#define OPTIONALLY_LAZY(type) \
LazyType_Base<type>&&
#pragma once
#include <type_traits>
#include <utility>
// Uses dynamic dispatch to permit lazy OR eager argument evaluation at the
// caller's discretion, with uniform access to the final value from the callee's
// perspective.
template <typename VAL_TYPE>
class LazyType_Base
{
protected:
// For LazyType_TrueLazy
template <typename CALLABLE>
LazyType_Base(CALLABLE&& expr)
{
static_assert(
std::is_same<
typename std::remove_reference<decltype(expr())>::type, VAL_TYPE
>::value,
"Expression does not evaluate to correct type!");
}
// For LazyType_Eager
// =default is not permitted by GCC here; see
// https://stackoverflow.com/q/38213809/1858225
LazyType_Base(void) {}
public:
// Both compilers suddenly fail when this is introduced, attempting to
// instantiate `LazyType_Base<LazyType_Base<VAL_TYPE>>`, which makes no
// sense. See https://stackoverflow.com/q/38214138/1858225
// In general, not making the destructor virtual *should* be safe as long as
// users are just using this type as it's intended (i.e. for lazy arguments
// to functions, to be used immediately or discarded without passing
// pointers around for deletion later).
// virtual ~LazyType_Base(void) =default;
virtual operator VAL_TYPE(void) =0;
};
// Takes an arbitrary expression and creates a class that will evaluate the
// expression when necessary.
template <typename VAL_TYPE, typename CALLABLE>
class LazyType_TrueLazy : public LazyType_Base<VAL_TYPE>
{
// friend LazyType_TrueLazy<VAL_TYPE, CALLABLE> MakeLazy<CALLABLE>(CALLABLE&& expr);
// With a working friend declaration, make all constructors private; `protect`
// default constructors in `LazyType_Base`
public:
LazyType_TrueLazy(CALLABLE&& expr)
: LazyType_Base<VAL_TYPE>{std::forward<CALLABLE>(expr)}
, expr_{std::forward<CALLABLE>(expr)}
{}
operator VAL_TYPE(void) override final
{
return expr_();
}
private:
CALLABLE expr_;
};
// If VAL_TYPE is the same as EXPR_TYPE, then we do not have a truly lazy
// instantiation.
template <typename VAL_TYPE>
class LazyType_Eager : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_Eager(
VAL_TYPE&& final_val)
: LazyType_Base<VAL_TYPE>{}
, val_{final_val}
{}
operator VAL_TYPE(void) override final
{
return val_;
}
private:
VAL_TYPE val_;
};
// C++14: since template `auto` arguments are not permitted prior to C++17,
// we need a helper function to evaluate the type of the callable, in case it's
// a lambda.
template <typename CALLABLE>
auto MakeLazy(CALLABLE&& expr)
{
return LazyType_TrueLazy<
typename std::remove_reference<decltype(expr())>::type, CALLABLE>{
std::forward<CALLABLE>(expr)};
}
#define LAZY_ARG(expr) \
MakeLazy([&](void)->auto { return expr; })
// Is there some way to create an implicit conversion to `LazyType_Eager` for
// all types that will be applied for any attempted conversion to
// `LazyType_Base`?
#define EAGER_ARG(val) \
LazyType_Eager<typename std::remove_reference<decltype(val)>::type>{val}
// Must provide a REFERENCE so that the actual type will not be sliced...but we
// don't actually want a mutable reference to a long-lived object, so we take an
// r-value reference. This is very simple to use with the `LAZY_ARG` and
// `EAGER_ARG` macros.
#define OPTIONALLY_LAZY(type) \
LazyType_Base<type>&&
EDIT: It seems proper to add a virtual destructor to LazyType_Base
, because both derived classes have actual data in them that should be cleaned up. However:
* Adding a virtual destructor causes a compile error: both G++ and Clang++ attempt to instantiate LazyType_Base<LazyType_Base<VAL_TYPE>>
. I have no idea why this is (I'll ask a StackOverflow question in a moment), but it's clearly incorrect.
* As long as users use the header as it's intended (with the macros), everything should work fine, since only the derived classes will be destroyed directly. Perhaps this could be enforced by =delete
-ing the copy and move constructors.
EDIT 2: links to SO questions:
- G++ doesn't permit use of
=default
constructor for base-class template - Existence of virtual destructor changes evaluation of seemingly-unrelated expression's type SOLVED
Let me just say that in a long list of C++ oddities, the two problems described in those questions might be the weirdest things I've encountered yet.EDIT: other known issues:
const
-correctness: This apparently does not work "out-of-the-box" forconst
types. I'm not sure why, but the compiler errors seem to indicate that this creates a temporary object of typeLazyType_Base
, which can't be done because it's pure-virtual. I don't know exactly why using aconst
value-type causes the creation of the temporary, though, when the non-const
version does not.
EDIT: It seems proper to add a virtual destructor to LazyType_Base
, because both derived classes have actual data in them that should be cleaned up. However:
* Adding a virtual destructor causes a compile error: both G++ and Clang++ attempt to instantiate LazyType_Base<LazyType_Base<VAL_TYPE>>
. I have no idea why this is (I'll ask a StackOverflow question in a moment), but it's clearly incorrect.
* As long as users use the header as it's intended (with the macros), everything should work fine, since only the derived classes will be destroyed directly. Perhaps this could be enforced by =delete
-ing the copy and move constructors.
EDIT 2: links to SO questions:
- G++ doesn't permit use of
=default
constructor for base-class template - Existence of virtual destructor changes evaluation of seemingly-unrelated expression's type
Let me just say that in a long list of C++ oddities, the two problems described in those questions might be the weirdest things I've encountered yet.
EDIT: links to SO questions:
- G++ doesn't permit use of
=default
constructor for base-class template - Existence of virtual destructor changes evaluation of seemingly-unrelated expression's type SOLVED
EDIT: other known issues:
const
-correctness: This apparently does not work "out-of-the-box" forconst
types. I'm not sure why, but the compiler errors seem to indicate that this creates a temporary object of typeLazyType_Base
, which can't be done because it's pure-virtual. I don't know exactly why using aconst
value-type causes the creation of the temporary, though, when the non-const
version does not.
Inspired by Swift's @autoclosure
feature, I tried writing a brief C++-14 header that permits "optionally" lazy parameters (i.e.by "lazy" I mean @autoclosure
-likelike; I chose the word "lazy" in emulation of lazy evaluation in languages such as Haskell) parameters. From this post on interesting Swift features:
I provide a macro, LAZY_PARAM
, that can be applied to parameters in function declarations; when calling these functions, arguments must be supplied using either the LAZY_ARG
macro, which uses reference-based closure-semantics to delay evaluation of the expression, or the EAGER_ARG
macro, which immediately evaluates the expression and wraps it in a light-weight class that simply stores the result. It's copied below and also available here. (NOTE: The linked version, on GitHub, will be kept up-to-date as I make changes, but the copied version may not.)
#pragma once
#include <type_traits>
#include <utility>
// Uses dynamic dispatch to permit lazy OR eager argument evaluation at the
// caller's discretion, with uniform access to the final value from the callee's
// perspective.
template <typename VAL_TYPE>
class LazyType_Base
{
protected:
// For LazyType_TrueLazy
template <typename CALLABLE>
LazyType_Base(CALLABLE&& expr)
{
static_assert(
std::is_same<
typename std::remove_reference<decltype(expr())>::type, VAL_TYPE
>::value,
"Expression does not evaluate to correct type!");
}
// For LazyType_Eager
// =default is not permitted by GCC herehere; see
// http://stackoverflow.com/q/38213809/1858225
LazyType_Base(void) {}
public:
// Both compilers suddenly fail when this is introduced, attempting to
// instantiate `LazyType_Base<LazyType_Base<VAL_TYPE>>`, which makes no
// sense. See http://stackoverflow.com/q/38214138/1858225
// In general, not making the destructor virtual *should* be safe as long as
// users are just using this type as it's intended (i.e. for lazy arguments
// to functions, to be used immediately or discarded without passing
// pointers around for deletion later).
// virtual ~LazyType_Base(void) =default;
virtual operator VAL_TYPE(void) =0;
};
// Takes an arbitrary expression and creates a class that will evaluate the
// expression when necessary.
template <typename VAL_TYPE, typename CALLABLE>
class LazyType_TrueLazy : public LazyType_Base<VAL_TYPE>
{
// friend LazyType_TrueLazy<VAL_TYPE, CALLABLE> MakeLazy<CALLABLE>(CALLABLE&& expr);
// With a working friend declaration, make all constructors private; `protect`
// default constructors in `LazyType_Base`
public:
LazyType_TrueLazy(CALLABLE&& expr)
: LazyType_Base<VAL_TYPE>{std::forward<CALLABLE>(expr)}
, expr_{std::forward<CALLABLE>(expr)}
{}
operator VAL_TYPE(void) override final
{
return expr_();
}
private:
CALLABLE expr_;
};
// If VAL_TYPE is the same as EXPR_TYPE, then we do not have a truly lazy
// instantiation.
template <typename VAL_TYPE>
class LazyType_Eager : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_Eager(
VAL_TYPE&& final_val)
: LazyType_Base<VAL_TYPE>{}
, val_{final_val}
{}
operator VAL_TYPE(void) override final
{
return val_;
}
private:
VAL_TYPE val_;
};
// C++14: since template `auto` arguments are not permitted prior to C++17,
// we need a helper function to evaluate the type of the callable, in case it's
// a lambda.
template <typename CALLABLE>
auto MakeLazy(CALLABLE&& expr)
{
return LazyType_TrueLazy<
typename std::remove_reference<decltype(expr())>::type, CALLABLE>({
std::forward<CALLABLE>(expr))};
}
#define LAZY_ARG(expr) \
MakeLazy([&](void)->auto { return expr; })
// Is there some way to create an implicit conversion to `LazyType_Eager` for
// all types that will be applied for any attempted conversion to
// `LazyType_Base`?
#define EAGER_ARG(val) \
LazyType_Eager<typename std::remove_reference<decltype(val)>::type>({val)}
// Must provide a REFERENCE so that the actual type will not be sliced...but we
// don't actually want a mutable reference to a long-lived object, so we take an
// r-value reference. This is very simple to use with the `LAZY_ARG` and
// `EAGER_ARG` macros.
#define OPTIONALLY_LAZY(type) \
LazyType_Base<type>&&
Inspired by Swift's @autoclosure
feature, I tried writing a brief C++-14 header that permits "optionally" lazy (i.e. @autoclosure
-like) parameters. From this post on interesting Swift features:
I provide a macro, LAZY_PARAM
, that can be applied to parameters in function declarations; when calling these functions, arguments must be supplied using either the LAZY_ARG
macro, which uses reference-based closure-semantics to delay evaluation of the expression, or the EAGER_ARG
macro, which immediately evaluates the expression and wraps it in a light-weight class that simply stores the result. It's copied below and also available here.
#pragma once
#include <type_traits>
// Uses dynamic dispatch to permit lazy OR eager argument evaluation at the
// caller's discretion, with uniform access to the final value from the callee's
// perspective.
template <typename VAL_TYPE>
class LazyType_Base
{
protected:
// For LazyType_TrueLazy
template <typename CALLABLE>
LazyType_Base(CALLABLE&& expr)
{
static_assert(
std::is_same<
typename std::remove_reference<decltype(expr())>::type, VAL_TYPE
>::value,
"Expression does not evaluate to correct type!");
}
// For LazyType_Eager
// =default is not permitted by GCC here
LazyType_Base(void) {}
public:
// Both compilers suddenly fail when this is introduced, attempting to
// instantiate `LazyType_Base<LazyType_Base<VAL_TYPE>>`, which makes no
// sense.
// virtual ~LazyType_Base(void) =default;
virtual operator VAL_TYPE(void) =0;
};
// Takes an arbitrary expression and creates a class that will evaluate the
// expression when necessary.
template <typename VAL_TYPE, typename CALLABLE>
class LazyType_TrueLazy : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_TrueLazy(CALLABLE&& expr)
: LazyType_Base<VAL_TYPE>{std::forward<CALLABLE>(expr)}
, expr_{std::forward<CALLABLE>(expr)}
{}
operator VAL_TYPE(void) override final
{
return expr_();
}
private:
CALLABLE expr_;
};
// If VAL_TYPE is the same as EXPR_TYPE, then we do not have a truly lazy
// instantiation.
template <typename VAL_TYPE>
class LazyType_Eager : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_Eager(
VAL_TYPE&& final_val)
: LazyType_Base<VAL_TYPE>{}
, val_{final_val}
{}
operator VAL_TYPE(void) override final
{
return val_;
}
private:
VAL_TYPE val_;
};
// C++14: since template `auto` arguments are not permitted prior to C++17,
// we need a helper function to evaluate the type of the callable, in case it's
// a lambda.
template <typename CALLABLE>
auto MakeLazy(CALLABLE&& expr)
{
return LazyType_TrueLazy<
typename std::remove_reference<decltype(expr())>::type, CALLABLE>(
std::forward<CALLABLE>(expr));
}
#define LAZY_ARG(expr) \
MakeLazy([&](void)->auto { return expr; })
// Is there some way to create an implicit conversion to `LazyType_Eager` for
// all types that will be applied for any attempted conversion to
// `LazyType_Base`?
#define EAGER_ARG(val) \
LazyType_Eager<typename std::remove_reference<decltype(val)>::type>(val)
// Must provide a REFERENCE so that the actual type will not be sliced...but we
// don't actually want a mutable reference to a long-lived object, so we take an
// r-value reference. This is very simple to use with the `LAZY_ARG` and
// `EAGER_ARG` macros.
#define OPTIONALLY_LAZY(type) \
LazyType_Base<type>&&
Inspired by Swift's @autoclosure
feature, I tried writing a brief C++-14 header that permits "optionally" lazy parameters (by "lazy" I mean @autoclosure
-like; I chose the word "lazy" in emulation of lazy evaluation in languages such as Haskell). From this post on interesting Swift features:
I provide a macro, LAZY_PARAM
, that can be applied to parameters in function declarations; when calling these functions, arguments must be supplied using either the LAZY_ARG
macro, which uses reference-based closure-semantics to delay evaluation of the expression, or the EAGER_ARG
macro, which immediately evaluates the expression and wraps it in a light-weight class that simply stores the result. It's copied below and also available here. (NOTE: The linked version, on GitHub, will be kept up-to-date as I make changes, but the copied version may not.)
#pragma once
#include <type_traits>
#include <utility>
// Uses dynamic dispatch to permit lazy OR eager argument evaluation at the
// caller's discretion, with uniform access to the final value from the callee's
// perspective.
template <typename VAL_TYPE>
class LazyType_Base
{
protected:
// For LazyType_TrueLazy
template <typename CALLABLE>
LazyType_Base(CALLABLE&& expr)
{
static_assert(
std::is_same<
typename std::remove_reference<decltype(expr())>::type, VAL_TYPE
>::value,
"Expression does not evaluate to correct type!");
}
// For LazyType_Eager
// =default is not permitted by GCC here; see
// http://stackoverflow.com/q/38213809/1858225
LazyType_Base(void) {}
public:
// Both compilers suddenly fail when this is introduced, attempting to
// instantiate `LazyType_Base<LazyType_Base<VAL_TYPE>>`, which makes no
// sense. See http://stackoverflow.com/q/38214138/1858225
// In general, not making the destructor virtual *should* be safe as long as
// users are just using this type as it's intended (i.e. for lazy arguments
// to functions, to be used immediately or discarded without passing
// pointers around for deletion later).
// virtual ~LazyType_Base(void) =default;
virtual operator VAL_TYPE(void) =0;
};
// Takes an arbitrary expression and creates a class that will evaluate the
// expression when necessary.
template <typename VAL_TYPE, typename CALLABLE>
class LazyType_TrueLazy : public LazyType_Base<VAL_TYPE>
{
// friend LazyType_TrueLazy<VAL_TYPE, CALLABLE> MakeLazy<CALLABLE>(CALLABLE&& expr);
// With a working friend declaration, make all constructors private; `protect`
// default constructors in `LazyType_Base`
public:
LazyType_TrueLazy(CALLABLE&& expr)
: LazyType_Base<VAL_TYPE>{std::forward<CALLABLE>(expr)}
, expr_{std::forward<CALLABLE>(expr)}
{}
operator VAL_TYPE(void) override final
{
return expr_();
}
private:
CALLABLE expr_;
};
// If VAL_TYPE is the same as EXPR_TYPE, then we do not have a truly lazy
// instantiation.
template <typename VAL_TYPE>
class LazyType_Eager : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_Eager(
VAL_TYPE&& final_val)
: LazyType_Base<VAL_TYPE>{}
, val_{final_val}
{}
operator VAL_TYPE(void) override final
{
return val_;
}
private:
VAL_TYPE val_;
};
// C++14: since template `auto` arguments are not permitted prior to C++17,
// we need a helper function to evaluate the type of the callable, in case it's
// a lambda.
template <typename CALLABLE>
auto MakeLazy(CALLABLE&& expr)
{
return LazyType_TrueLazy<
typename std::remove_reference<decltype(expr())>::type, CALLABLE>{
std::forward<CALLABLE>(expr)};
}
#define LAZY_ARG(expr) \
MakeLazy([&](void)->auto { return expr; })
// Is there some way to create an implicit conversion to `LazyType_Eager` for
// all types that will be applied for any attempted conversion to
// `LazyType_Base`?
#define EAGER_ARG(val) \
LazyType_Eager<typename std::remove_reference<decltype(val)>::type>{val}
// Must provide a REFERENCE so that the actual type will not be sliced...but we
// don't actually want a mutable reference to a long-lived object, so we take an
// r-value reference. This is very simple to use with the `LAZY_ARG` and
// `EAGER_ARG` macros.
#define OPTIONALLY_LAZY(type) \
LazyType_Base<type>&&