STYLE: Replace non-POD string constants with constexpr QLatin1String - #1440
STYLE: Replace non-POD string constants with constexpr QLatin1String#1440lassoan wants to merge 1 commit into
Conversation
4372137 to
b9fd9c9
Compare
Static QString variables have non-trivial constructors and destructors,
triggering clazy:non-pod-global-static and introducing Static
Initialization Order Fiasco (SIOF) risk. All affected constants are
pure compile-time string literals, now defined as constexpr
QLatin1String. No call-site changes are required -- QLatin1String
implicitly converts to QString for all existing uses.
Qt5 / Apple-clang compatibility: QLatin1String(const char*) calls
strlen(), which is not constexpr under Apple clang. A new CTKCore
header, ctkStringLiterals.h, provides a backport of Qt 6.4's
Qt::StringLiterals::operator""_L1:
constexpr QLatin1String operator""_L1(const char* str, std::size_t size)
{ return QLatin1String{str, static_cast<int>(size)}; }
The compiler supplies the literal length to the user-defined literal
operator, so no strlen() is involved and construction is fully
constexpr on all supported compilers. Definition sites are one-liners:
constexpr QLatin1String PREFIX_EXECUTABLE = "executable:"_L1;
The operator has external linkage and is shared by all translation
units, so it is also safe to use in headers (an internal-linkage helper
in an anonymous namespace would make in-class initializers an ODR
violation). Once CTK requires Qt >= 6.4 the header can be retired in
favor of Qt::StringLiterals with no call-site changes.
For ctkPluginFrameworkDebug, the ten OPTION_DEBUG_* class static
members are converted to static constexpr in the private header using
the literal and a #define CTK_OSGI prefix macro (scoped with #undef);
string-literal concatenation is applied before the literal suffix, so
CTK_OSGI "/debug"_L1 works. The out-of-line QString definitions and
the CTK_OSGI QString variable are removed from the .cpp entirely
(in-class static constexpr members are implicitly inline in C++17).
The redundant 'static' specifier is omitted on all anonymous-namespace
members (internal linkage is already implied by the enclosing
namespace).
Co-authored-by: Hans J. Johnson <hans-johnson@uiowa.edu>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
b9fd9c9 to
dbee151
Compare
|
Reviewed and build-tested this locally against Worth flagging first: CI does not compile any of the six files this PR touches. Build and test evidence (Qt5 + Qt6, proposed vs upstream/master)Configuration:
All five changed Tests, same configuration, both refs: Call sites were checked individually: every converted constant reaches either a Why the downstream Slicer axis could not be exercisedI normally validate CTK changes through a 3D Slicer superbuild as well. That is not informative for this PR, for a structural reason: Slicer sets For completeness: my local Slicer superbuild tree also failed to configure on both refs (a stale path baked into its cache, unrelated to this PR), so even that limited signal is absent. I did not want to imply downstream coverage that does not exist. Suggestion 1 — version-guard
|
This is a potential alternative solution to the same problem described in #1410, with a simpler syntax and without potential ODR violation issue.
Static QString variables have non-trivial constructors and destructors, triggering clazy:non-pod-global-static and introducing Static Initialization Order Fiasco (SIOF) risk. All affected constants are pure compile-time string literals, now defined as constexpr QLatin1String. No call-site changes are required -- QLatin1String implicitly converts to QString for all existing uses.
Qt5 / Apple-clang compatibility: QLatin1String(const char*) calls strlen(), which is not constexpr under Apple clang. A new CTKCore header, ctkStringLiterals.h, provides a backport of Qt 6.4's Qt::StringLiterals::operator""_L1:
constexpr QLatin1String operator""_L1(const char* str, std::size_t size)
{ return QLatin1String{str, static_cast(size)}; }
The compiler supplies the literal length to the user-defined literal operator, so no strlen() is involved and construction is fully constexpr on all supported compilers. Definition sites are one-liners:
constexpr QLatin1String PREFIX_EXECUTABLE = "executable:"_L1;
The operator has external linkage and is shared by all translation units, so it is also safe to use in headers (an internal-linkage helper in an anonymous namespace would make in-class initializers an ODR violation). Once CTK requires Qt >= 6.4 the header can be retired in favor of Qt::StringLiterals with no call-site changes.
For ctkPluginFrameworkDebug, the ten OPTION_DEBUG_* class static members are converted to static constexpr in the private header using the literal and a #define CTK_OSGI prefix macro (scoped with #undef); string-literal concatenation is applied before the literal suffix, so CTK_OSGI "/debug"_L1 works. The out-of-line QString definitions and the CTK_OSGI QString variable are removed from the .cpp entirely (in-class static constexpr members are implicitly inline in C++17).
The redundant 'static' specifier is omitted on all anonymous-namespace members (internal linkage is already implied by the enclosing namespace).