如何强制字符串字面量触发std::string的类模板推导
实现方案
你不需要修改原有Scalar类的单模板参数设计,只需要利用C++17引入的类模板实参推导(CTAD)自定义推导指引,就能实现直接传入字符串字面量时自动推导为std::string的效果,完全不需要对char*/char[]做类模板特化。
具体实现
原有类模板定义保持不变,只需要在类定义的同级作用域添加几行推导规则,覆盖所有字符串相关的入参类型:
#include <string> #include <cstddef> template <typename T> class Scalar { public: explicit Scalar(const T& val) : value_(val) {} private: T value_; }; // 自定义CTAD推导指引 template <std::size_t N> Scalar(const char(&)[N]) -> Scalar<std::string>; // 匹配字符串字面量(const char[N]类型) Scalar(const char*) -> Scalar<std::string>; // 匹配const char*指针 Scalar(char*) -> Scalar<std::string>; // 匹配char*指针
效果说明
- 直接调用
Scalar("hello")时,编译器会自动匹配数组类型的推导指引,最终实例化Scalar<std::string>类型,不需要你显式指定模板参数 - 传入非字符串类型参数(比如
int/double/自定义类对象)时,仍然走默认的模板推导规则,不会被字符串规则干扰 - 类本身始终保持单个模板参数的设计,不需要新增模板参数,也不需要编写针对字符类型的模板特化,所有字符串存储统一使用
std::string
注:该方案依赖C17及以上标准,目前GCC 8+、Clang 6+、MSVC 2017及以上版本均已完整支持该特性。如果需要兼容C17之前的标准,没有办法通过类名直接隐式推导模板参数,只能通过你之前提到的显式指定模板参数、或者额外写
make_scalar工厂函数的方式实现。
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

