基于C++17 CTAD实现自定义比较函子模板实参自动推导咨询
问题原因分析
原代码无法运行的核心原因有两点:
Compare是类模板,没有显式指定模板参数、也没有提供推导指引的情况下,编译器无法自动推导模板参数T的类型- 原代码的写法
Compare(b1, b2)是尝试调用类的构造函数创建实例,并未调用比较用的operator(),不符合函子的调用规范
C++17
std::less的实现原理 std::less能够免传模板参数使用,依赖两个核心特性:
std::less<void>特化:这是一个透明比较器,它的operator()本身是模板函数,可以自动推导入参类型,不需要在类层面指定模板参数- 类模板实参推导(CTAD)指引:当不指定模板参数创建
std::less实例时,编译器会自动匹配推导指引,将模板参数推导为void,使用透明特化版本
改造方案
方案1:实现透明比较器(最简洁,适配通用场景)
如果你的比较逻辑不需要针对特定类型做差异化特化,直接将operator()实现为模板函数即可:
struct Base{}; // 不再是类模板,operator()泛型支持任意类型 struct Compare { template<typename T> bool operator()(const T& a, const T& b) const { // 替换为实际比较逻辑 return true; } }; int main() { Base b1, b2; // 先创建Compare实例,再调用operator() return Compare{}(b1, b2); }
方案2:保留类模板,添加CTAD推导指引
如果需要针对不同类型做Compare的特化,保留类模板结构的同时添加推导指引即可:
struct Base{}; template<typename T> struct Compare { bool operator()(const T& a, const T& b) const { return true; } }; // 透明特化版本,转发到对应类型的Compare实现 template<> struct Compare<void> { template<typename T> bool operator()(const T& a, const T& b) const { return Compare<T>{}(a, b); } }; // 添加CTAD推导指引 // 无参构造时推导为Compare<void> Compare() -> Compare<void>; // 传入两个T类型参数时推导为Compare<T> template<typename T> Compare(const T&, const T&) -> Compare<T>; int main() { Base b1, b2; // 两种调用方式均支持 Compare{}(b1, b2); // 走透明特化 Compare(b1, b2)(b1, b2); // 构造时推导T为Base,再调用operator() return 0; }
内容的提问来源于stack exchange,提问作者pepero
相关产品推荐
相关产品推荐

