# Dependent typing in C++

A dependent type is a type that has a dependency on a value. It essentially is way to encode values into the type, that is, every value has a unique type. Non-type template parameters in C++ allow this. Also, `std::integral_constant`

is good example of dependent typing. Say we want to represent the value `3`

we can write:

```
using three_t = std::integral_constant<int, 3>;
```

So if we want to pass `3`

to another function we could just construct the type, like this:

```
std::vector<int> v(three_t()); // A vector of size three
```

Now there is a difference between dependent types and constexpr values, for example:

```
constexpr void check_positive(int n)
{
static_assert(n > 0, "Value isn't positive"); // Compile error
}
```

This doesn’t work because `int`

is not a dependent type even though it is used in `constexpr`

. We could change it to be a template instead:

```
template<class N>
constexpr void check_positive(N n)
{
static_assert(n > 0, "Value isn't positive");
}
```

So this works, if we pass in `three_t`

to `check_positive`

:

```
check_positive(three_t());
```

## Operators

Now, `std::integral_constant`

is somewhat awkward when you want to write math:

```
template<class T, class U>
auto sum(T x, U y)
{
return std::integral_constant<int, T::value + U::value>();
}
```

Instead, lets use the `tick::integral_constant`

class from Tick. This class extends `std::integral_constant`

with all the non-mutable operators, so we could write the `sum`

function like this:

```
template<class T, class U>
auto sum(T x, U y)
{
return x + y;
}
```

Which is the same as it would be for any generic `sum`

functions. So we can call it like this:

```
template<int N>
using int_ = tick::integral_constant<int, N>;
auto three = sum(int_<1>(), int_<2>());
```

Or it could be written simply:

```
auto three = int_<1>() + int_<2>();
```

What is important is how we can write natural syntax to calculate values at compile-time(without using `constexpr`

as well, which is not always guaranteed to be at compile-time).

## Filtering tuples

Now, say we want to filter a tuple based on a predicate. For example, we may want to only print the values in a tuple that are numbers. We can do that currently using Boost.Fusion with `filter_if`

like this:

```
template<class Tuple>
void print_numbers(const Tuple& t)
{
for_each(filter_if<std::is_integral<_>>(t), [](auto x)
{
std::cout << x << std::endl;
});
}
print_numbers(std::make_tuple(1, 2, std::vector<int>()));
```

Now the `std::is_integral<_>`

is a placeholder expression. Boost.Fusion uses Boost.MPL library to replace the `_`

with each type thats in the tuple, and then it evaluates the result. Now, this may not be the worse syntax, but it gets uglier when we want to do something more complicated. For example, we could check if the type `is_integral`

or `is_floating_point`

:

```
template<class Tuple>
void print_numbers(const Tuple& t)
{
for_each(filter_if<or_<std::is_integral<_>, std::is_floating_point<_>>>(t), [](auto x)
{
std::cout << x << std::endl;
});
}
print_numbers(std::make_tuple(1, 2.5, std::vector<int>()));
```

Now, we can improve this a lot by using depedent typing. Let’s look how to implement an improved `filter_if`

called `simple_filter`

, that accepts a C++ function object or lambda for the predicate instead. To understand a little better how `filter_if`

works, the functions takes either a placeholder expression or a metafunction class. So lets make a metafunction class that will return the result of the function `F`

called with type `T`

:

```
template<class F>
struct predicate
{
template<class T>
struct apply
{
using type = decltype(std::declval<F>()(std::declval<T>());
};
};
```

With this, we can write the `simple_filter`

function:

```
template<class Tuple, class Predicate>
auto simple_filter(Tuple&& t, Predicate)
{
return filter_if<predicate<Predicate>>(std::forward<Tuple>(t));
}
```

Next, lets wrap the traits so they use `tick::integral_constant`

instead.

```
template<class T>
using enhance = tick::integral_constant<typename T::value_type, T::value>;
template<class T>
using is_integral = enhance<std::is_integral<T>>;
template<class T>
using is_floating_point = enhance<std::is_floating_point<T>>;
```

And finally, we can now write `print_numbers`

more naturally:

```
template<class Tuple>
void print_numbers(const Tuple& t)
{
auto numbers = simple_filter(t, [](auto x)
{
return is_integral<decltype(x)>() or is_floating_point<decltype(x)>();
});
for_each(numbers, [](auto x)
{
std::cout << x << std::endl;
});
}
print_numbers(std::make_tuple(1, 2.5, std::vector<int>()));
```

Although using the placeholder expression is more compact, using a lambda for the predicate looks more “natural”. Finally, after writing `simple_filter`

, we are able to filter tuples at compile time without needing to write `constexpr`

nor use template meta-programming.

Of course, this idea is not entirely new. Zach Laine and Matt Calabrese explored similar ideas many years ago at BoostCon in their presentation Instatiations Must Go(slides here). Their original goal was to try to improve performance of metaprogramming by avoiding instantiating templates explicitly, however, in the process they discovered a way to write template metaprogramming using more natural C++ syntax.