Keywords: C++ | constexpr | std::string | character array | string_view
Abstract: This article provides an in-depth analysis of the compatibility issues between constexpr and std::string in C++11 and subsequent standards. By examining compiler error messages, it explains the fundamental reason why std::string cannot be used in constexpr declarations—its non-trivial destructor. The article details alternative approaches using character arrays and compares improvements in C++17's string_view and C++20. Through practical code examples, it demonstrates how to handle string constants at compile time, offering developers actionable solutions.
Problem Background and Analysis
In the C++11 standard environment, developers attempting to use constexpr std::string constString = "constString"; encounter compilation errors. The compiler explicitly states the reason: the type std::basic_string<char> has a non-trivial destructor, thus it does not meet the requirements of a literal type.
Root Cause Explanation
The constexpr keyword requires that the variable type must be a literal type. According to the C++ standard, a literal type must satisfy conditions such as having a trivial destructor and all non-static data members being literal types. std::string, as a dynamic string container, typically involves dynamic memory allocation in its implementation, resulting in a non-trivial destructor, which prevents it from meeting constexpr requirements.
Alternative Implementation
The most straightforward solution is to use a character array: constexpr char constString[] = "constString";. This declaration creates a string constant at compile time, which can be converted to a std::string object at runtime via std::string str(constString);.
Evolution of C++ Standards
C++17 introduced std::string_view, providing string view functionality: constexpr std::string_view sv = "hello, world";. string_view acts as a non-owning reference to a string, suitable for read-only scenarios and meeting constexpr requirements.
C++20 further relaxed restrictions, allowing std::string to be used during constant evaluation, but requiring it to be destroyed by the end of constant evaluation. For example, constexpr std::size_t n = std::string("hello, world").size(); compiles successfully.
Practical Application Case
Referencing a compilation error case in the spdlog logging library, when attempting to initialize an array with string_view in a constant expression, compilation fails due to the invocation of the non-constexpr function strlen. This further validates that only compile-time evaluable operations can be used in constant expressions.
Best Practices Recommendation
For scenarios requiring compile-time string handling, it is recommended to choose the appropriate solution based on the C++ standard version: use character arrays for C++11/14, string_view for C++17, and limited use of std::string for C++20. In practical projects, considerations for code portability and compatibility should be thoroughly evaluated.