# The new static constexpr std::integral_constant idiom

This blog post was first published at think-cell's developer blog. Subscribe there to stay up-to-date!

The size of `std::array<T, N>`

is known at compile-time given the type.
Yet it only provides a regular `.size()`

member function:

```
template <typename T, std::size_t N>
struct array {
constexpr std::size_t size() const {
return N;
}
};
```

This is annoying if you’re writing generic code that expects some sort of compile-time sized range.

```
template <typename Rng>
void algorithm(Rng const& rng) {
constexpr auto a = Rng::size(); // error, std::array has no static size
constexpr auto b = rng.size(); // error, not a constant expression
constexpr auto c = std::tuple_size<Rng>::value; // okay, but ugly
}
```

It would be really nice if `std::array::size`

were a `static`

member function instead:

```
template <typename T, std::size_t N>
struct array {
static constexpr std::size_t size() {
return N;
}
};
```

Now we can just use `::size()`

to get the size of an array without breaking existing code:
You can still call static member functions with `.`

syntax;
`foo.static_member(args)`

is equivalent to `std::remove_cvref_t<decltype(foo)>::static_member(args)`

.
There are MISRA guidelines against it and a clang-tidy check that complains, but it is really useful for generic code.

However, sometimes even `Rng::size()`

isn’t enough.
Suppose we want to have a `std::integral_constant`

as the result, so we can do type-based metaprogramming.
Sure, we can then write `std::integral_constant<std::size_t, Rng::size()>{}`

, but that’s a lot to type.
It would be really convenient if `std::array`

had that directly, as that is the “most `constexpr`

” version of a size:

```
template <typename T, std::size_t N>
struct array {
static constexpr std::integral_constant<std::size_t, N> size = {};
};
```

Now we can write `array::size`

and get a `std::integral_constant`

that represents the size.
But we’ve broken all code that assumed `.size()`

or `::size()`

?

You’d think so, but no: `std::integral_constant`

has a call operator!

```
template <typename T, T Value>
struct integral_constant {
constexpr T operator()() const {
return Value;
}
};
```

So with a single member, we support:

`array::size`

, which results in a`std::integral_constant`

object.`array::size()`

, which calls the`operator()`

on the`std::integral_constant`

and returns a`std::size_t`

.`array_obj.size()`

, which is the same as above and returns a`std::size_t`

, just as a member function.

Now that is nice!

The library evolution group of the C++ committee is considering that idiom for all new standard library components with constant sizes, like `std::simd`

, or `std::inplace_vector::capacity`

(formerly `std::static_vector::capacity`

).
Of course, we can’t actually change `std::array`

due to ABI or something…