Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Quick-n-Dirty Type Categorization

Much has already been written about dispatching on type traits using SFINAE (Substitution Failure Is Not An Error) techniques in C++. There is a Boost library, Boost.Enable_if, to make the technique idiomatic. Proto dispatches on type traits extensively, but it doesn't use enable_if<> very often. Rather, it dispatches based on the presence or absence of nested types, often typedefs for void.

Consider the implementation of is_expr<>. It could have been written as something like this:

template<typename T>
struct is_expr
  : is_base_and_derived<proto::some_expr_base, T>
{};

Rather, it is implemented as this:

template<typename T, typename Void = void>
struct is_expr
  : mpl::false_
{};

template<typename T>
struct is_expr<T, typename T::proto_is_expr_>
  : mpl::true_
{};

This relies on the fact that the specialization will be preferred if T has a nested proto_is_expr_ that is a typedef for void. All Proto expression types have such a nested typedef.

Why does Proto do it this way? The reason is because, after running extensive benchmarks while trying to improve compile times, I have found that this approach compiles faster. It requires exactly one template instantiation. The other approach requires at least 2: is_expr<> and is_base_and_derived<>, plus whatever templates is_base_and_derived<> may instantiate.


PrevUpHomeNext