constexpr中使用可选throw的作用?编译时strlen异常写法疑问
Awesome question! That throw statement sitting in an unreachable branch of the constexpr strlen might look totally useless at first glance, but it’s actually a clever workaround for older C++ constexpr rules (pre-C++17) with some real practical value. Let’s break it down:
1. Forces Compile-Time Only Execution
Back in C11 and C14, constexpr functions could run either at compile time or runtime—compilers had some flexibility here. If you passed a value that wasn’t a compile-time constant (like a pointer to a buffer filled while the program was running), the compiler would default to running the function at runtime.
The throw here acts as a link-time trap. The err::strlen_runtime_error is declared as extern but almost certainly never defined in the codebase. When the compiler has to generate runtime code for this function (because it can’t compute it at compile time), it’ll need a definition for that extern variable—and since there isn’t one, you’ll get a link error. This effectively locks the function into only being usable with compile-time constants (like string literals), guaranteeing the strlen calculation happens during compilation, not when your program runs.
2. Mimics consteval Before It Existed
C++20 introduced consteval, which explicitly marks a function as compile-time only—calling it with a runtime value is a compile error, no link step needed. But before that, this throw trick was a way to approximate that behavior.
Even though the throw branch is unreachable, it’s structured so that the runtime path of the function relies on an undefined extern. So anyone trying to use the function in a runtime context gets a hard error, just like they would with consteval today.
A Quick Example
- If you call
strlen("hello world"), the compiler evaluates theconstexpr_func()branch at compile time, completely ignores the throw, and spits out the constant 11—smooth sailing. - If you try something like
char buf[20]; cin >> buf; int len = strlen(buf);, the compiler can’t compute this at compile time. It tries to generate runtime code, hits the missing definition forerr::strlen_runtime_error, and throws a link error stopping you in your tracks.
It’s a neat little hack that solved a real problem before the language had official support for compile-time-only functions.
内容的提问来源于stack exchange,提问作者Fred

