[#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]

