如何使用std::wstring_view作为std::map的std::wstring键及实现语法糖?
我尝试构建一个以std::wstring为键的std::map结构,希望通过宏和std::wstring_view简化常量键的声明与定义。当前map定义如下:
class Parameter { public: typedef std::wstring Key; std::variant<void*, int, bool, float, std::wstring> value_; ... } typedef std::map<Parameter::Key, Parameter> Parameters;
使用字符串字面量访问map无问题:
myParameters[L"SomeKey"] = L"SomeValue";
但使用std::wstring_view定义常量键时出现错误:
static constexpr std::wstring_view SomeKeyDefined = L"SomeKey"; myParameters[SomeKeyDefined] = L"SomeValue";
错误信息:
C2679: binary '[': no operator found which takes a right-hand operand of type 'const std::wstring_view' (or there is no acceptable conversion)
我原以为std::wstring_view是const std::wstring的包装,想咨询是否可以用std::wstring_view作为该map的键?最终我希望通过宏实现语法糖来定义常量键,例如:
#define PARAMETER_KEY_STRING(x) L # x #define PARAMETER_KEY(name) static constexpr std::wstring_view name = PARAMETER_KEY_STRING(name);
从而可以通过PARAMETER_KEY(SomeKey)来定义常量键。若此方式不可行,有没有其他实现std::wstring常量键语法糖的方法?
关于std::wstring_view作为map键的疑问
std::wstring_view并非const std::wstring的包装,它只是对宽字符序列的非拥有式视图,两者属于不同类型。std::map<std::wstring, ...>的operator[]仅接受能隐式转换为std::wstring的类型,而std::wstring_view到std::wstring不存在隐式转换(需要显式构造),因此直接用wstring_view访问会触发编译错误。
要使用wstring_view操作现有map,有两种可行方案:
- 显式转换为
std::wstring:访问时手动构造wstring对象,示例如下:
缺点是每次访问都会生成临时myParameters[std::wstring(SomeKeyDefined)] = L"SomeValue";wstring,存在额外的内存分配与拷贝开销。 - 修改map键类型为
std::wstring_view:如果键对应的字符串(比如常量字面量)生命周期长于map,这种方式安全且高效,因为wstring_view不管理内存,避免了wstring的构造开销:
此时用typedef std::map<std::wstring_view, Parameter> Parameters;wstring_view常量键直接访问map即可正常编译运行。
实现std::wstring常量键的语法糖
若坚持使用std::wstring作为map键,可调整宏定义直接生成const std::wstring类型的常量:
#define PARAMETER_KEY(name) static const std::wstring name = L#name;
使用PARAMETER_KEY(SomeKey)定义后,SomeKey就是const std::wstring类型,直接用myParameters[SomeKey]访问不会有类型问题。
针对C++17及以上版本,建议用inline变量避免多定义问题:
#define PARAMETER_KEY(name) inline static const std::wstring name = L#name;
内容的提问来源于stack exchange,提问作者lfgtm

