C++OnSea 2025 SESSION ANNOUNCEMENT: Balancing Efficiency and Flexibility: Cost of Abstractions in Embedded Systems by Marcell Juhasz

https://cpponsea.uk/2025/session/balancing-efficiency-and-flexibility-cost-of-abstractions-in-embedded-systems

Register now at https://cpponsea.uk/tickets/

#consteval #constexpr #cpp #template

C++ on Sea

C++OnSea 2025 SESSION ANNOUNCEMENT: Balancing Efficiency and Flexibility: Cost of Abstractions in Embedded Systems by Marcell Juhasz

https://cpponsea.uk/2025/session/balancing-efficiency-and-flexibility-cost-of-abstractions-in-embedded-systems

Register now at https://cpponsea.uk/tickets/

#consteval #constexpr #cpp #template

C++ on Sea

🌗 C++26:標準函式庫中更多 constexpr
➤ C++26 將編譯時期程式設計提升至新高度
https://www.sandordargo.com/blog/2025/04/30/cpp26-constexpr-library-changes
本文探討了 C++26 即將推出的標準函式庫中,更多功能將能在編譯時期使用 (constexpr)。文章重點介紹了關於穩定排序、`<cmath>` 和 `<complex>`、trivial unions、容器和adaptors、以及特殊記憶體演算法的提案,以及這些變更如何提升編譯時期程式設計的能力。總體而言,C++26 在 constexpr 的支援上邁出了一大步,未來編譯時期程式設計將更加普及且強大。
+ 哇,這個更新太棒了!constexpr 幫助我避免了許多執行時期的錯誤,現在能用在更多標準函式庫功能上,簡直是夢寐以求的。
+ 雖然有一些細節比較複雜,但整體來看,C++26 的這些改變真的很有意義,讓 C++ 更加強大和高效。
#C++ #程式設計 #constexpr
C++26: more constexpr in the standard library

Last week, we discussed language features that are becoming constexpr in C++26. Today, let’s turn our attention to the standard library features that will soon be usable at compile time. One topic is missing: exceptions. As they need both core language and library changes, I thought they deserved their own post. P2562R1: constexpr stable sorting This paper proposes making std::stable_sort, std::stable_partition, std::inplace_merge, and their ranges counterparts usable in constant expressions. While many algorithms have become constexpr over the years, this family related to stable sorting had remained exceptions — until now. The recent introduction of constexpr containers gives extra motivation for this proposal. If you can construct a container at compile time, it’s only natural to want to sort it there, too. More importantly, a constexpr std::vector can now support efficient, stable sorting algorithms. A key question is whether the algorithm can meet its computational complexity requirements under the constraints of constant evaluation. Fortunately, std::is_constant_evaluated() provides an escape hatch for implementations. For deeper details, check out the proposal itself. P1383R2: More constexpr for <cmath> and <complex> While P0533 made many <cmath> and <cstdlib> functions constexpr-friendly in C++23, it only addressed functions with trivial behavior — those no more complex than the basic arithmetic operators. Floating-point computations can yield different results depending on compiler settings, optimization levels, and hardware platforms. For instance, calculating std::sin(1e100) may produce varying outcomes due to the intricacies of floating-point arithmetic at such scales. The paper discusses these challenges and suggests that some variability in results is acceptable, given the nature of floating-point computations. The proposal accepts the need for a balance between strict determinism and practical flexibility. It suggests that while some functions should produce consistent results across platforms, others may inherently allow for some variability. P3074R7: trivial unions (was std::uninitialized<T>) To implement static, in-place, constexpr-friendly containers like non-allocating vectors, you often need uninitialized storage — typically via unions. However, default behavior for special members of unions has been limiting: if not all alternatives are trivial, the special member is deleted. This presents a problem for constexpr code where a no-op destructor isn’t quite the same as a trivial one. The road to solving this wasn’t short: P3074R7 went through seven revisions and considered five possible solutions—including library-based approaches, new annotations, and even a new union type. Ultimately, the committee decided to just make it work with minimal changes to the user experience. But how? For unions, the default constructor - if there is no default member initializer - is always going to be trivial. If the first alternative is an implicit-lifetime time, it begins its life-time and becomes the active member. The defaulted destructor is deleted if either the union has a user-provided default constructor or there exists a variant alternative that has a default member initializer and that member’s destructor is either deleted or inaccessible. Otherwise, the destructor is trivial. This excerpt from the proposal shows the changes well. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // trivial default constructor (does not start lifetime of s) // trivial destructor // (status quo: deleted default constructor and destructor) union U1 { string s; }; // non-trivial default constructor // deleted destructor // (status quo: deleted destructor) union U2 { string s = "hello"; } // trivial default constructor // starts lifetime of s // trivial destructor // (status quo: deleted default constructor and destructor) union U3 { string s[10]; } // non-trivial default constructor (initializes next) // trivial destructor // (status quo: deleted destructor) union U4 { string s; U4* next = nullptr; }; P3372R2: constexpr containers and adaptors Hana Dusíková authored a massive proposal that boils down to a simple goal: make (almost) all containers and adaptors constexpr. Up until now, only a handful of them were constexpr-friendly (std::vector, std::span, std::mdspan, std::basic_string and std::basic_string_view). From now on, the situation will be flipped. Almost everything will be constexpr-friendly. There is one exception and one constraint: std::hive is not included, because it doesn’t have a stable wording yet if you want to use unordered containers at compile-time, you must provide your own hashing facility, because std::hash cannot be made constexpr-friendly due to its requirements. Its result is guaranteed to be consistent only with the duration of the program. Happy days! P3508R0: Wording for “constexpr for specialized memory algorithms” Such a strange title, isn’t? Wording for something… As it turns out, there was already a paper accepted (P2283R2) making specialized memory algorithms constexpr-friendly. Algorithms that are essential for implementing constexpr container support, yet they were forgotten from C++20. These algorithms are (both in std and in std::ranges namespaces): uninitialized_value_construct uninitialized_value_construct_n uninitialized_copy uninitialized_copy_result uninitialized_copy_n uninitialized_copy_n_result uninitialized_move uninitialized_move_result uninitialized_move_n uninitialized_move_n_result uninitialized_fill uninitialized_fill_n When the paper was made, the necessary implementation change was to use std::construct_at instead of placement new, as std::consturct_at was already constexpr. But in the meantime, P2747R2 was accepted and placement new in the core language also became constexpr. Therefore, the implementation of the above functions doesn’t have to be changed, only their signatures have to be updated to support constexpr. Hence, the wording change. P3369R0: constexpr for uninitialized_default_construct We saw that the constexpr placement new affected P2283R2 and raised the need for a wording change performed in P3508R0. But that’s not the only side-effect it had. From the above-listed algorithm families, one is missing: uninitialized_default_construct. The reason is that uninitialized_default_construct cannot be implemented with std::construct_at as it always performs value initialization, default initialization was impossible. But with constexpr placement new this is not an issue anymore, therefore uninitialized_default_construct can also be turned into constexpr. Conclusion C++26 marks a huge step forward for constexpr support in the standard library. From stable sorting algorithms to containers, from tricky union rules to specialised memory functions, compile-time programming is becoming more and more supported. In the next article, we’ll cover compile-time exceptions! Connect deeper If you liked this article, please hit on the like button, subscribe to my newsletter and let’s connect on Twitter!

Sandor Dargo’s Blog
Ah, yet another riveting chapter in the never-ending #C++ saga 📚! This time, it's the thrilling tale of #constexpr infiltrating the standard library, because who doesn’t love waiting for the next version of a language to get basic compile-time functionality? 🤷‍♂️ Exciting news for those who find watching paint dry too exhilarating! 🎨
https://www.sandordargo.com/blog/2025/04/30/cpp26-constexpr-library-changes #C++StandardLibrary #CompileTime #ProgrammingHumor #HackerNews #ngated
C++26: more constexpr in the standard library

Last week, we discussed language features that are becoming constexpr in C++26. Today, let’s turn our attention to the standard library features that will soon be usable at compile time. One topic is missing: exceptions. As they need both core language and library changes, I thought they deserved their own post. P2562R1: constexpr stable sorting This paper proposes making std::stable_sort, std::stable_partition, std::inplace_merge, and their ranges counterparts usable in constant expressions. While many algorithms have become constexpr over the years, this family related to stable sorting had remained exceptions — until now. The recent introduction of constexpr containers gives extra motivation for this proposal. If you can construct a container at compile time, it’s only natural to want to sort it there, too. More importantly, a constexpr std::vector can now support efficient, stable sorting algorithms. A key question is whether the algorithm can meet its computational complexity requirements under the constraints of constant evaluation. Fortunately, std::is_constant_evaluated() provides an escape hatch for implementations. For deeper details, check out the proposal itself. P1383R2: More constexpr for <cmath> and <complex> While P0533 made many <cmath> and <cstdlib> functions constexpr-friendly in C++23, it only addressed functions with trivial behavior — those no more complex than the basic arithmetic operators. Floating-point computations can yield different results depending on compiler settings, optimization levels, and hardware platforms. For instance, calculating std::sin(1e100) may produce varying outcomes due to the intricacies of floating-point arithmetic at such scales. The paper discusses these challenges and suggests that some variability in results is acceptable, given the nature of floating-point computations. The proposal accepts the need for a balance between strict determinism and practical flexibility. It suggests that while some functions should produce consistent results across platforms, others may inherently allow for some variability. P3074R7: trivial unions (was std::uninitialized<T>) To implement static, in-place, constexpr-friendly containers like non-allocating vectors, you often need uninitialized storage — typically via unions. However, default behavior for special members of unions has been limiting: if not all alternatives are trivial, the special member is deleted. This presents a problem for constexpr code where a no-op destructor isn’t quite the same as a trivial one. The road to solving this wasn’t short: P3074R7 went through seven revisions and considered five possible solutions—including library-based approaches, new annotations, and even a new union type. Ultimately, the committee decided to just make it work with minimal changes to the user experience. But how? For unions, the default constructor - if there is no default member initializer - is always going to be trivial. If the first alternative is an implicit-lifetime time, it begins its life-time and becomes the active member. The defaulted destructor is deleted if either the union has a user-provided default constructor or there exists a variant alternative that has a default member initializer and that member’s destructor is either deleted or inaccessible. Otherwise, the destructor is trivial. This excerpt from the proposal shows the changes well. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // trivial default constructor (does not start lifetime of s) // trivial destructor // (status quo: deleted default constructor and destructor) union U1 { string s; }; // non-trivial default constructor // deleted destructor // (status quo: deleted destructor) union U2 { string s = "hello"; } // trivial default constructor // starts lifetime of s // trivial destructor // (status quo: deleted default constructor and destructor) union U3 { string s[10]; } // non-trivial default constructor (initializes next) // trivial destructor // (status quo: deleted destructor) union U4 { string s; U4* next = nullptr; }; P3372R2: constexpr containers and adaptors Hana Dusíková authored a massive proposal that boils down to a simple goal: make (almost) all containers and adaptors constexpr. Up until now, only a handful of them were constexpr-friendly (std::vector, std::span, std::mdspan, std::basic_string and std::basic_string_view). From now on, the situation will be flipped. Almost everything will be constexpr-friendly. There is one exception and one constraint: std::hive is not included, because it doesn’t have a stable wording yet if you want to use unordered containers at compile-time, you must provide your own hashing facility, because std::hash cannot be made constexpr-friendly due to its requirements. Its result is guaranteed to be consistent only with the duration of the program. Happy days! P3508R0: Wording for “constexpr for specialized memory algorithms” Such a strange title, isn’t? Wording for something… As it turns out, there was already a paper accepted (P2283R2) making specialized memory algorithms constexpr-friendly. Algorithms that are essential for implementing constexpr container support, yet they were forgotten from C++20. These algorithms are (both in std and in std::ranges namespaces): uninitialized_value_construct uninitialized_value_construct_n uninitialized_copy uninitialized_copy_result uninitialized_copy_n uninitialized_copy_n_result uninitialized_move uninitialized_move_result uninitialized_move_n uninitialized_move_n_result uninitialized_fill uninitialized_fill_n When the paper was made, the necessary implementation change was to use std::construct_at instead of placement new, as std::consturct_at was already constexpr. But in the meantime, P2747R2 was accepted and placement new in the core language also became constexpr. Therefore, the implementation of the above functions doesn’t have to be changed, only their signatures have to be updated to support constexpr. Hence, the wording change. P3369R0: constexpr for uninitialized_default_construct We saw that the constexpr placement new affected P2283R2 and raised the need for a wording change performed in P3508R0. But that’s not the only side-effect it had. From the above-listed algorithm families, one is missing: uninitialized_default_construct. The reason is that uninitialized_default_construct cannot be implemented with std::construct_at as it always performs value initialization, default initialization was impossible. But with constexpr placement new this is not an issue anymore, therefore uninitialized_default_construct can also be turned into constexpr. Conclusion C++26 marks a huge step forward for constexpr support in the standard library. From stable sorting algorithms to containers, from tricky union rules to specialised memory functions, compile-time programming is becoming more and more supported. In the next article, we’ll cover compile-time exceptions! Connect deeper If you liked this article, please hit on the like button, subscribe to my newsletter and let’s connect on Twitter!

Sandor Dargo’s Blog
C++26: more constexpr in the standard library

Last week, we discussed language features that are becoming constexpr in C++26. Today, let’s turn our attention to the standard library features that will soon be usable at compile time. One topic is missing: exceptions. As they need both core language and library changes, I thought they deserved their own post. P2562R1: constexpr stable sorting This paper proposes making std::stable_sort, std::stable_partition, std::inplace_merge, and their ranges counterparts usable in constant expressions. While many algorithms have become constexpr over the years, this family related to stable sorting had remained exceptions — until now. The recent introduction of constexpr containers gives extra motivation for this proposal. If you can construct a container at compile time, it’s only natural to want to sort it there, too. More importantly, a constexpr std::vector can now support efficient, stable sorting algorithms. A key question is whether the algorithm can meet its computational complexity requirements under the constraints of constant evaluation. Fortunately, std::is_constant_evaluated() provides an escape hatch for implementations. For deeper details, check out the proposal itself. P1383R2: More constexpr for <cmath> and <complex> While P0533 made many <cmath> and <cstdlib> functions constexpr-friendly in C++23, it only addressed functions with trivial behavior — those no more complex than the basic arithmetic operators. Floating-point computations can yield different results depending on compiler settings, optimization levels, and hardware platforms. For instance, calculating std::sin(1e100) may produce varying outcomes due to the intricacies of floating-point arithmetic at such scales. The paper discusses these challenges and suggests that some variability in results is acceptable, given the nature of floating-point computations. The proposal accepts the need for a balance between strict determinism and practical flexibility. It suggests that while some functions should produce consistent results across platforms, others may inherently allow for some variability. P3074R7: trivial unions (was std::uninitialized<T>) To implement static, in-place, constexpr-friendly containers like non-allocating vectors, you often need uninitialized storage — typically via unions. However, default behavior for special members of unions has been limiting: if not all alternatives are trivial, the special member is deleted. This presents a problem for constexpr code where a no-op destructor isn’t quite the same as a trivial one. The road to solving this wasn’t short: P3074R7 went through seven revisions and considered five possible solutions—including library-based approaches, new annotations, and even a new union type. Ultimately, the committee decided to just make it work with minimal changes to the user experience. But how? For unions, the default constructor - if there is no default member initializer - is always going to be trivial. If the first alternative is an implicit-lifetime time, it begins its life-time and becomes the active member. The defaulted destructor is deleted if either the union has a user-provided default constructor or there exists a variant alternative that has a default member initializer and that member’s destructor is either deleted or inaccessible. Otherwise, the destructor is trivial. This excerpt from the proposal shows the changes well. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // trivial default constructor (does not start lifetime of s) // trivial destructor // (status quo: deleted default constructor and destructor) union U1 { string s; }; // non-trivial default constructor // deleted destructor // (status quo: deleted destructor) union U2 { string s = "hello"; } // trivial default constructor // starts lifetime of s // trivial destructor // (status quo: deleted default constructor and destructor) union U3 { string s[10]; } // non-trivial default constructor (initializes next) // trivial destructor // (status quo: deleted destructor) union U4 { string s; U4* next = nullptr; }; P3372R2: constexpr containers and adaptors Hana Dusíková authored a massive proposal that boils down to a simple goal: make (almost) all containers and adaptors constexpr. Up until now, only a handful of them were constexpr-friendly (std::vector, std::span, std::mdspan, std::basic_string and std::basic_string_view). From now on, the situation will be flipped. Almost everything will be constexpr-friendly. There is one exception and one constraint: std::hive is not included, because it doesn’t have a stable wording yet if you want to use unordered containers at compile-time, you must provide your own hashing facility, because std::hash cannot be made constexpr-friendly due to its requirements. Its result is guaranteed to be consistent only with the duration of the program. Happy days! P3508R0: Wording for “constexpr for specialized memory algorithms” Such a strange title, isn’t? Wording for something… As it turns out, there was already a paper accepted (P2283R2) making specialized memory algorithms constexpr-friendly. Algorithms that are essential for implementing constexpr container support, yet they were forgotten from C++20. These algorithms are (both in std and in std::ranges namespaces): uninitialized_value_construct uninitialized_value_construct_n uninitialized_copy uninitialized_copy_result uninitialized_copy_n uninitialized_copy_n_result uninitialized_move uninitialized_move_result uninitialized_move_n uninitialized_move_n_result uninitialized_fill uninitialized_fill_n When the paper was made, the necessary implementation change was to use std::construct_at instead of placement new, as std::consturct_at was already constexpr. But in the meantime, P2747R2 was accepted and placement new in the core language also became constexpr. Therefore, the implementation of the above functions doesn’t have to be changed, only their signatures have to be updated to support constexpr. Hence, the wording change. P3369R0: constexpr for uninitialized_default_construct We saw that the constexpr placement new affected P2283R2 and raised the need for a wording change performed in P3508R0. But that’s not the only side-effect it had. From the above-listed algorithm families, one is missing: uninitialized_default_construct. The reason is that uninitialized_default_construct cannot be implemented with std::construct_at as it always performs value initialization, default initialization was impossible. But with constexpr placement new this is not an issue anymore, therefore uninitialized_default_construct can also be turned into constexpr. Conclusion C++26 marks a huge step forward for constexpr support in the standard library. From stable sorting algorithms to containers, from tricky union rules to specialised memory functions, compile-time programming is becoming more and more supported. In the next article, we’ll cover compile-time exceptions! Connect deeper If you liked this article, please hit on the like button, subscribe to my newsletter and let’s connect on Twitter!

Sandor Dargo’s Blog

C++26: more constexpr in the core language | Hacker News

LinkC++26:核心語言中更多 constexpr 功能的演進
https://sandordargo.com/cpp26-more-constexpr-in-the-core-language

📌 Summary:
自 C++11 引入 constexpr 以來,constexpr 的應用範圍持續擴大,從最初不支援 if、else、迴圈,到 C++14 允許控制流程,C++17 支援 constexpr lambdas,C++20 更進一步允許動態配置和使用 std::vector 及 std::string。到了 C++26,constexpr 功能獲得更多強化,包括可在常數表達式中從 void 做指標轉型(P2738R1)、支援在 constexpr 中使用 placement new(P2747R2),以及允許宣告 constexpr structured bindings 且放寬 constexpr 參考的綁定規則(P2686R5)。這些語言層面的改變將使更多標準函式庫類型和功能能在編譯期進行運算,進一步提升程式碼效率與安全性。此外,未來還將探討 constexpr 支援例外處理與標準函式庫的延伸。此演進不僅推動編譯期編程由傳統模板技巧轉為更直觀且可驗證的方式,也為編譯器實作帶來新挑戰。

🎯 Key Points:
→ P2738R1:C++26 允許在 constexpr 表達式中從 void 指標轉型到物件實際類型的指標,限制不可轉向不同類型或基類指標。此設計可支援更多標準函式庫元件(如 std::format、std::function、std::any)在編譯期運作,主要因為 void 用於減少模板實例化和二進位符號數量的「編譯防火牆」技巧。
→ P2747R2:新增 constexpr 版本的 placement new,可彌補 std::construct_at 僅支援值初始化的不足,使得在 constexpr 環境下更靈活地進行物件預置建立。此功能須仰賴 P2738R1 中 void 指標轉型的支持解決類型轉換問題。
→ P2686R5:允許宣告 constexpr structured bindings,並放寬 constexpr 參考綁定規則。constexpr 參考可綁定於自動存取期間且相對於堆疊框架地址不變的變數,但例如 lambda 捕獲的外層變數因無法確定常數地址而不符條件,故有限制。此改進讓 constexpr 編寫更靈活、結構化。
→ 綜合以上,C++26 大幅推動 constexpr 技術由語言核心擴展,為日後標準函式庫更多 constexpr 化奠定基礎,並促進從繁複模板元編程向更語義明確、編譯期安全的編程模式轉變。
→ 使用者與開發者須留意編譯器實作狀況,目前多數主流編譯器對 C++20 甚至 C++23 支援仍未完全,C++26 的新功能落地仍需時間。
→ 文章後續將描述標準函式庫的 constexpr 支援演進,以及 constexpr 例外處理的相關變化,需結合語言與函式庫面雙重改良。

🔖 Keywords:
#constexpr #C++26 #void轉型 #placement_new #structured_bindings

C++26: more constexpr in the core language | Hacker News

Apparently, #C++ developers are so smitten with `constexpr` that they're willing to sacrifice their first-born to it in #C++26. 🤷‍♂️ Gone are the days of simple "Hello, World" — now it's all about wrangling `constexpr` lambdas while hoping the compiler gods smile upon you. 😅
https://www.sandordargo.com/blog/2025/04/23/cpp26-constexpr-language-changes #constexpr #programming #humor #developercommunity #HackerNews #ngated
C++26: more constexpr in the core language

Since constexpr was added to the language in C++11, its scope has been gradually expanded. In the beginning, we couldn’t even use if, else or loops, which were changed in C++14. C++17 added support for constexpr lambdas. C++20 added the ability to use allocation and use std::vector and std::string in constant expressions. In this article, let’s see how constexpr evolves with C++26. To be more punctual, let’s see what language features become more constexpr-friendly. We’ll discuss library changes in a separate article, as well as constexpr exceptions, which need both language and library changes. P2738R1: constexpr cast from void* Thanks to the acceptance of P2738R1, starting from C++26, one can cast from void* to a pointer of type T in constant expressions, if the type of the object at that adress is exactly the type of T. Note that conversions to interconvertible - including pointers to base classes - or not related types are not permitted. The motivation behind this change is to make several standard library functions or types work at compile time. To name a few examples: std::format, std::function, std::function_ref, std::any. The reason why this change will allow many more for more constexpr in the standard library is that storing void* is a commonly used compilation firewall technique to reduce template instantiations and the number of symbols in compiled binaries. P2747R2: constexpr placement new As std::construct_at is a limited tool that only allows to perform value initialization but not others such as default or list initialization, there has been a need to make placement new usable in constant expressions. At the same time, placement new is a very, maybe even too flexible tool and to use it in a safe way requires casting to void* and then back to T*. This faced some issues, but the acceptance of P2738R1 and the ability of casting from void* in constant expressions made the impossible possible. If you are looking for more details, check P2747R2. P2686R5: constexpr structured bindings and references to constexpr variables This is a rather long (20 pages) proposal and I found it not particularly easy to read. That’s not the fault of the authors, the problem is hard to address. The paper which is based on another, went through 5 revisions, discusses various solutions, and lists the wording changes on more than 10 pages. Long story short, you’ll be able to declare structured bindings constexpr. As structured bindings behave like references, the same restrictions apply as to constexpr references. Those restrictions become more relaxed. Before, a constexpr reference had to bind to a variable with static storage duration, so that the address doesn’t change from one evaluation to another. With C++26, in addition, variables with automatic storage duration are also accepted if and only if the address is constant relative to the stack frame in which the reference or the structured binding lives. In practice, this means that you cannot have a constexpr reference in a lambda to bind to an enclosing function. The reason is that in order to access that variable, the expression is something like this->__x where __x represents the captured address of x. As we don’t know at compile time what object this points to, it’s not a constant expression. Conclusion In this article, we reviewed how constexpr evolves in the C++26 core language. We are getting constexpr cast from void*, placement new, structured bindings and even exceptions (not discussed today). In the next article, we’ll see how the standard library’s constexpr support evolves. Connect deeper If you liked this article, please hit on the like button, subscribe to my newsletter and let’s connect on Twitter!

Sandor Dargo’s Blog
C++26: more constexpr in the core language

Since constexpr was added to the language in C++11, its scope has been gradually expanded. In the beginning, we couldn’t even use if, else or loops, which were changed in C++14. C++17 added support for constexpr lambdas. C++20 added the ability to use allocation and use std::vector and std::string in constant expressions. In this article, let’s see how constexpr evolves with C++26. To be more punctual, let’s see what language features become more constexpr-friendly. We’ll discuss library changes in a separate article, as well as constexpr exceptions, which need both language and library changes. P2738R1: constexpr cast from void* Thanks to the acceptance of P2738R1, starting from C++26, one can cast from void* to a pointer of type T in constant expressions, if the type of the object at that adress is exactly the type of T. Note that conversions to interconvertible - including pointers to base classes - or not related types are not permitted. The motivation behind this change is to make several standard library functions or types work at compile time. To name a few examples: std::format, std::function, std::function_ref, std::any. The reason why this change will allow many more for more constexpr in the standard library is that storing void* is a commonly used compilation firewall technique to reduce template instantiations and the number of symbols in compiled binaries. P2747R2: constexpr placement new As std::construct_at is a limited tool that only allows to perform value initialization but not others such as default or list initialization, there has been a need to make placement new usable in constant expressions. At the same time, placement new is a very, maybe even too flexible tool and to use it in a safe way requires casting to void* and then back to T*. This faced some issues, but the acceptance of P2738R1 and the ability of casting from void* in constant expressions made the impossible possible. If you are looking for more details, check P2747R2. P2686R5: constexpr structured bindings and references to constexpr variables This is a rather long (20 pages) proposal and I found it not particularly easy to read. That’s not the fault of the authors, the problem is hard to address. The paper which is based on another, went through 5 revisions, discusses various solutions, and lists the wording changes on more than 10 pages. Long story short, you’ll be able to declare structured bindings constexpr. As structured bindings behave like references, the same restrictions apply as to constexpr references. Those restrictions become more relaxed. Before, a constexpr reference had to bind to a variable with static storage duration, so that the address doesn’t change from one evaluation to another. With C++26, in addition, variables with automatic storage duration are also accepted if and only if the address is constant relative to the stack frame in which the reference or the structured binding lives. In practice, this means that you cannot have a constexpr reference in a lambda to bind to an enclosing function. The reason is that in order to access that variable, the expression is something like this->__x where __x represents the captured address of x. As we don’t know at compile time what object this points to, it’s not a constant expression. Conclusion In this article, we reviewed how constexpr evolves in the C++26 core language. We are getting constexpr cast from void*, placement new, structured bindings and even exceptions (not discussed today). In the next article, we’ll see how the standard library’s constexpr support evolves. Connect deeper If you liked this article, please hit on the like button, subscribe to my newsletter and let’s connect on Twitter!

Sandor Dargo’s Blog

Okay, let's see how long it takes for this feature to get implemented in clang …

https://github.com/llvm/llvm-project/issues/135764

#clang #cpp20 #constexpr

[clang] Expose constexpr evaluation statistics · Issue #135764 · llvm/llvm-project

When compiling constexpr-heavy code it would be nice to receive more feedback than "constexpr evaluation hit maximum step limit" or "constexpr evaluation exceeded maximum depth of N calls". Especia...

GitHub

C++Now 2025 SESSION ANNOUNCEMENT: Harnessing constexpr - A Path to Safer C++ by Mikhail Svetkin

https://schedule.cppnow.org/session/2025/harnessing-constexpr/

Register now at https://cppnow.org/registration/

#coding #constexpr #cplusplus #cpp

Harnessing constexpr – C++Now Schedule