63 lines
1.7 KiB
Plaintext
63 lines
1.7 KiB
Plaintext
[#lazy_metafunction]
|
|
[section Lazy template metafunction]
|
|
|
|
A ['lazy template metafunction] is a [link metafunction template metafunction]
|
|
that accepts [link nullary_metafunction nullary metafunction]s as arguments,
|
|
that need to be evaluated first to get the value of the argument.
|
|
|
|
For example here is a `plus` metafunction for `int` values:
|
|
|
|
template <class A, class B>
|
|
struct plus :
|
|
std::integral_constant<int, A::value + B::value>
|
|
{};
|
|
|
|
This metafunction takes two [link boxed_value boxed] numbers as arguments,
|
|
unboxes them, adds their values and boxed the result again.
|
|
|
|
It works when it is called with boxed numbers. For example:
|
|
|
|
static_assert(
|
|
plus<
|
|
std::intgeral_constant<int, 2>,
|
|
std::integral_constant<int, 2>
|
|
>::type::value == 4,
|
|
"This should work"
|
|
);
|
|
|
|
However, when it is called with a nullary metafunction returning the boxed
|
|
value, it breaks:
|
|
|
|
struct nullary_metafunction_returning_2
|
|
{
|
|
using type = std::integral_constant<int, 2>;
|
|
};
|
|
|
|
// Fails to compile
|
|
plus<nullary_metafunction_returning_2, nullary_metafunction_returning_2>::type
|
|
|
|
So `plus` is ['not] a lazy template metafunction. To make it lazy, it has to
|
|
evaluate its arguments before using them:
|
|
|
|
template <class A, class B>
|
|
struct lazy_plus :
|
|
std::integral_constant<int, A::type::value + B::type::value>
|
|
{};
|
|
|
|
Note that it uses `A::type::value` and `B::type::value` instead of `A::value`
|
|
and `B::value`. It works when it is called with nullary metafunctions as well:
|
|
|
|
static_assert(
|
|
plus<
|
|
nullary_metafunction_returning_2,
|
|
nullary_metafunction_returning_2
|
|
>::type::value == 4,
|
|
"This should work"
|
|
);
|
|
|
|
Because it works with nullary metafunctions as arguments, it is a lazy template
|
|
metafunction.
|
|
|
|
[endsect]
|
|
|