如何在编译时将std::string转为哈希值用于C++模板非类型参数?
为何再提字符串转哈希问题
我的问题与热门问题《How to convert a std::string to const char* or char*》类似,但要求在编译时生成哈希值。以下是详细说明:
动机
我正在构建的多线程框架中,为遵循ODR规则并保持可维护性,线程需复用功能相同的文件。错误日志模块需直接复用,因此每个线程需独立的errorLogger实例。
拟议方案
将ErrorLogger类模板化,使用常量非类型参数。若能在编译时对唯一标识字符串生成哈希值,即可用该哈希值作为模板参数来生成独立的ErrorLogger实例。
以下是无法运行的示例代码:
#include <string> std::string threadUniqueStr { "threadUniqueName" }; /*constexpr*/ auto threadUniqueHash = std::hash< std::string > {} ( threadUniqueStr ); // 取消constexpr注释会报错:表达式未计算为常量 template< size_t > void Func() {} int main() { //Func< threadUniqueHash >(); // 错误:表达式未计算为常量 Func< 33 >(); // 运行正常 }
或许存在更简便的C++实现方式?
编辑1:初步解决方案
参考string_view哈希方案(需自行编写constexpr哈希函数),但考虑到哈希冲突风险及多开发者协作场景的需求,我决定构建ErrorLogger类层次结构。
编辑2:最终解决方案
我采用最初的设计思路,利用string_view的constexpr哈希生成唯一值,为每个项目创建显式模板特化,将ErrorLogger相关代码放入特化的静态区域。代码结构示例如下:
头文件定义
// .h template< size_t ProjectNameNumT > void INFOMSG(); template< size_t ProjectNameNumT > void INFOMSG( bool yesNo );
项目A全局实例
// 项目A全局定义 ErrorLogger< PROJ_A_HASH > errorLoggerProjA;
项目B全局实例
// 项目B全局定义 ErrorLogger< PROJ_B_HASH > errorLoggerProjB;
模板特化实现
// .cpp 特化实现 template<> void INFOMSG< PROJ_A_HASH >() { errorLoggerProjA.initLoggerHasRun = true; }
该方案在保证接口易用性的同时,满足了ODR合规要求。
内容的提问来源于stack exchange,提问作者rtischer8277
相关产品推荐
相关产品推荐

