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