This is my learning notes from the course - Mastering C++ Standard Library Features .
constexpr
in the Standard Library
constexpr
in the Standard Library (C++11/14/17)
Use case examples
Why?
Having the Standard Library support constexpr
algorithms and data structures out-of-the-box:
Allows people to reuse familiar abstractions for compile-time programming
Reduces separation of the community (For example: constexpr
libraries versus run-time libraries)
C++11
For C++11, the standard committee was very conservative with adding constexpr
to Standard Library facilities for several reasons:
Work was mostly focused on constexpr
as a language feature
Implementation freedom would have been severely limited (the C++11 constexpr
restrictions were severe)
Evaluating which functions could or could not be marked as constexpr required a huge effort
Constants: std::numeric_limits
, std::char_traits
, <random>
header engine constants, and more
Many default constructors (For example: std::pair
, std::tuple
)
std::bitset
: construction from unsigned int
, size()
and operator[]
std::ratio
and std::chrono::{duration, time_point}
std::array::size
std::atomic<T>
construction from T
C++14
Relaxed constexpr
rules in C++14 paved the way for a more constexpr
Standard Library:
std::pair
and std::tuple
‘s constructors, data access, and comparisons
std::forward
, std::move
, and std::move_if_noexcept
std::complex
‘s comparisons and literal suffixes
std::min
and std::max
<functional>
utilities like std::less
and std::greater
C++17
In C++17, constexpr
was already part of the original design of several new library features:
std::string_view
std::optional
std::variant
Uniform container access: std::size
, std::empty
, std::data
Example: Counting std::array
Elements Matching a Predicate 1 2 3 4 5 6 7 8 template <typename T>constexpr std ::size_t count_true (const std ::array <bool , N>& a) { std ::size_t result = 0 ; for (const auto & x : a) if (x) ++result; return result; }
Can be used both at run-time and compile-time
In C++20, you can use std::count
or std::count_if
Example: Calculating Buffer Size for Multiple Types 1 2 3 4 5 template <typename ... Ts>using storage_for = std ::aligned_storage_t < std ::max({sizeof (Ts) ... }), std ::max({alignof (Ts) ... }) >;
std::aligned_storage<Len, Align>
is uninitialized storage for any object whose size is at most Len
and suitable for Align
std::max(std::initializer_list<T>)
is constexpr
since C++14
This could be used to implement a type-safe union alternative (For example, std::variant
)1 2 3 4 5 6 template <typename ... Ts>class variant { storage_for<Ts ...> _storage; };
In face, the Standard Library provides std::aligned_union
which is implemented similarly to storage_for
Example: Parsing Strings at Compile-Time 1 2 3 4 5 6 7 8 constexpr auto parse_person (std ::string_view s) { const auto mid = s.find_first_of(';' ); return std ::make_tuple( s.substr(0 , mid), s.substr(mid + 1 , s.size() - mid) ); }
std::make_tuple
marked constexpr
since C++14
std::string_view
introduced in C++17
1 2 3 4 5 6 constexpr auto name = "Bjarne;Stroustrup" ;constexpr auto fst_name = std ::get<0 >(parse_person(name));constexpr auto lst_name = std ::get<1 >(parse_person(name));static_assert (fst_name == std ::string_view{"Bjarne" });static_assert (lst_name == std ::string_view{"Stroustrup" });
std::get
marked constexpr
since C++14
std::string_view
comparisons are constexpr
Note that parse_person
could also be used at run-time
Summary
Learned that the Standard Library is increasingly getting more constexpr
-friendly
Understood that since C++14, many general-purpose utilities can be safely used in constexpr
functions (For example: std::pair
, std::tuple
, std::min
, std::max
)
Learned that in C++17 and the upcoming C++20, even more Standard Library algorithms and data structures will be marked as constexpr
Guidelines
Use std::pair
or std::tuple
when returning multiple values from constexpr
functions
std::string_view
is constexpr
-friendly: use it when writing functions that need to parse/validate strings
Test your constexpr
functions at compile-time by using static_assert
Reference Link