类模板能否为同一构造函数定义多个用户自定义推导指南?
在C++类模板中定义多个用户自定义推导指南是否合法?
合法性结论
完全合法。C++标准允许为类模板定义多个用户自定义推导指南,无论这些指南是否对应同一个构造函数,只要推导指南的语法和约束符合标准要求即可。
你的示例代码是合法的:
#include <concepts> #include <string> #include <utility> template<typename T> class A { T t; public: A(T t): t(std::move(t)) { /* ... */ } }; template<typename T> requires ( std::floating_point<std::remove_cvref_t<T>> || std::integral<std::remove_cvref_t<T>> ) A(T&& a) -> A<double>; A(const char* s) -> A<std::string>;
多个适配推导指南的选择规则
当存在多个可行的推导指南(包括构造函数隐式生成的推导候选和用户自定义推导指南)时,编译器会通过重载决议选择最佳匹配,核心规则如下:
- 特化程度优先:非模板推导指南优先于模板推导指南;更特化的模板推导指南优先于更通用的模板推导指南。比如示例中传入字符串字面量
A("test")时,非模板的A(const char* s) -> A<std::string>会优先被选中。 - 约束满足优先:只有满足
requires约束的推导指南才会被纳入候选集;若多个指南都满足约束,再比较特化程度和类型匹配度。 - 类型匹配精度优先:推导过程中,类型匹配越精确(如cv限定符、引用类型的匹配)的指南优先级越高。
结合示例的具体场景:
- 传入整数(如
A(10))或浮点数(如A(3.14f))时,会触发带requires约束的模板推导指南,最终推导出A<double>类型的对象。 - 传入
const char*类型参数(如字面量字符串)时,会触发非模板推导指南,推导出A<std::string>类型的对象。
内容的提问来源于stack exchange,提问作者Amir Kirsh
相关产品推荐
相关产品推荐

