From 27c5b9e78b8dae359e9725992fbc8aa1ee7ee822 Mon Sep 17 00:00:00 2001 From: Willi Schinmeyer Date: Mon, 10 Jun 2024 10:51:07 +0200 Subject: [PATCH] Rework TemplateString for standard compliance Creating an std::integer_sequence from a user-defined string literal is a non-standard gcc extension. This alternative implementation should conform to C++20. --- tools/quake3/q3map2/autopk3.cpp | 2 +- tools/quake3/q3map2/convert_map.cpp | 2 +- tools/quake3/q3map2/map.cpp | 4 ++-- tools/quake3/q3map2/q3map2.h | 25 +++++++++++++++---------- tools/quake3/q3map2/surface_meta.cpp | 2 +- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/tools/quake3/q3map2/autopk3.cpp b/tools/quake3/q3map2/autopk3.cpp index 17858f1b..59ca6231 100644 --- a/tools/quake3/q3map2/autopk3.cpp +++ b/tools/quake3/q3map2/autopk3.cpp @@ -107,7 +107,7 @@ static void parseBspFile( const char *bspPath, StrList& outShaders, StrList& out } for ( size_t i = 0; i < bspShaders.size(); ++i ){ - if ( drawsurfSHs[i] && !( bspShaders[i].surfaceFlags & GetRequiredSurfaceParm( "nodraw"_Tstring ).surfaceFlags ) ){ // also sort out nodraw patches + if ( drawsurfSHs[i] && !( bspShaders[i].surfaceFlags & GetRequiredSurfaceParm<"nodraw">().surfaceFlags ) ){ // also sort out nodraw patches res2list( pk3Shaders, bspShaders[i].shader ); } } diff --git a/tools/quake3/q3map2/convert_map.cpp b/tools/quake3/q3map2/convert_map.cpp index 855a04f9..1edef52a 100644 --- a/tools/quake3/q3map2/convert_map.cpp +++ b/tools/quake3/q3map2/convert_map.cpp @@ -340,7 +340,7 @@ static void ConvertBrush( FILE *f, int bspBrushNum, const Vector3& origin, bool /* find out if brush is detail */ int contentFlag = 0; - if( !( bspShaders[bspBrushes[bspBrushNum].shaderNum].contentFlags & GetRequiredSurfaceParm( "structural"_Tstring ).contentFlags ) ){ // sort out structural transparent brushes, e.g. hints + if( !( bspShaders[bspBrushes[bspBrushNum].shaderNum].contentFlags & GetRequiredSurfaceParm<"structural">().contentFlags ) ){ // sort out structural transparent brushes, e.g. hints for( const auto& leaf : bspLeafs ){ if( leaf.cluster >= 0 ) for( auto id = bspLeafBrushes.cbegin() + leaf.firstBSPLeafBrush, end = id + leaf.numBSPLeafBrushes; id != end; ++id ){ diff --git a/tools/quake3/q3map2/map.cpp b/tools/quake3/q3map2/map.cpp index 7fd2e48d..eb184449 100644 --- a/tools/quake3/q3map2/map.cpp +++ b/tools/quake3/q3map2/map.cpp @@ -496,10 +496,10 @@ static void SetBrushContents( brush_t& b ){ else if ( s->compileFlags & C_FOG ){ b.contentShader = s->shaderInfo; } - else if ( b.contentShader->contentFlags & GetRequiredSurfaceParm( "playerclip"_Tstring ).contentFlags ){ + else if ( b.contentShader->contentFlags & GetRequiredSurfaceParm<"playerclip">().contentFlags ){ continue; } - else if ( s->contentFlags & GetRequiredSurfaceParm( "playerclip"_Tstring ).contentFlags ){ + else if ( s->contentFlags & GetRequiredSurfaceParm<"playerclip">().contentFlags ){ b.contentShader = s->shaderInfo; } else if (!( b.contentShader->compileFlags & C_SOLID )){ diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index 694413ea..a30d395f 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -67,6 +67,7 @@ #include "bitflags.h" #include #include +#include #include "qmath.h" #include @@ -1662,17 +1663,21 @@ void TCMod( const tcMod_t& mod, Vector2& st ); bool ApplySurfaceParm( const char *name, int *contentFlags, int *surfaceFlags, int *compileFlags ); const surfaceParm_t *GetSurfaceParm( const char *name ); -// Encode the string as a type -template -using TemplateString = std::integer_sequence; -// Create a user defined literal operator -template -constexpr TemplateString operator""_Tstring() { return { }; } +// Encode the string as a structural literal class type +template +struct TemplateString +{ + consteval TemplateString( const char(&string)[N] ) { + std::copy_n( string, N, m_data ); + ENSURE( string[N - 1] == '\0' && "TemplateString must be null-terminated" ); // consteval ensures this is evaluated at compile time, despite not being a static_assert + } + char m_data[N]; +}; + /// \brief returns statically evaluated \c surfaceParm_t for the given name or emits \c Error -template -const surfaceParm_t &GetRequiredSurfaceParm( const TemplateString ){ - static constexpr char str[sizeof...(chars) + 1] = { chars..., '\0' }; // Recover the character data - static const surfaceParm_t *const sp = GetSurfaceParm( str ); +template +const surfaceParm_t &GetRequiredSurfaceParm(){ + static const surfaceParm_t *const sp = GetSurfaceParm( string.m_data ); // null-termination ensured in constructor ENSURE( sp != nullptr ); return *sp; } diff --git a/tools/quake3/q3map2/surface_meta.cpp b/tools/quake3/q3map2/surface_meta.cpp index bc53c199..09b0b6fb 100644 --- a/tools/quake3/q3map2/surface_meta.cpp +++ b/tools/quake3/q3map2/surface_meta.cpp @@ -383,7 +383,7 @@ static void TriangulatePatchSurface( const entity_t& e, mapDrawSurface_t *ds ){ memcpy( dsNew, ds, sizeof( *ds ) ); /* if the patch is nonsolid, then discard it */ - if ( !( ds->shaderInfo->compileFlags & C_SOLID ) && !( ds->shaderInfo->contentFlags & GetRequiredSurfaceParm( "playerclip"_Tstring ).contentFlags ) ) { + if ( !( ds->shaderInfo->compileFlags & C_SOLID ) && !( ds->shaderInfo->contentFlags & GetRequiredSurfaceParm<"playerclip">().contentFlags ) ) { ClearSurface( ds ); }