能否为C++模板添加推导指引以根据接收函数推导正确类型?
当然可以实现这个需求!不过得先说明:C++默认不会从函数调用的上下文(比如接收函数的参数类型)反向推导函数模板的返回值模板参数,所以我们需要一些小技巧来达成目标。下面给你两种实用方案:
方案1:用代理类实现自动类型适配(最简洁)
这种方法不需要写模板推导指引,而是通过一个代理对象的模板转换运算符,让编译器自动根据接收函数的参数类型完成转换:
#include <iostream> // 代理类,能隐式转换为任意类型 struct ReturnProxy { template <typename TargetType> operator TargetType() const { // 可添加自定义逻辑,比如打印转换类型 std::cout << "自动转换到类型: " << typeid(TargetType).name() << "\n"; return TargetType{}; } }; // 返回代理对象的普通函数(非模板) ReturnProxy return_r() { return {}; } void accep_float(float arg) { std::cout << "收到float参数: " << arg << "\n"; } int main() { accep_float(return_r()); // 自动转换为float,完美匹配需求! }
运行这段代码,编译器会在调用accep_float时,自动触发ReturnProxy到float的转换,完全不需要显式指定模板参数。
方案2:类模板+推导指引(贴合你的提问思路)
如果你确实想通过模板推导指引来实现,可以把return_r封装为类模板的静态成员,然后为类模板添加推导指引,让编译器从目标类型反推模板参数:
#include <iostream> #include <type_traits> template <typename R> struct ReturnR { // 静态方法返回R类型对象 static R return_r() { std::cout << "返回类型: " << typeid(R).name() << "\n"; return R{}; } // 为支持推导指引,添加接收R类型的构造函数(仅用于推导,实际不调用) explicit ReturnR(R) {} }; // 推导指引:当构造函数接收类型T时,推导模板参数R=T template <typename T> ReturnR(T) -> ReturnR<T>; // 辅助函数:通过临时对象触发推导指引,返回对应类型结果 template <typename TargetType> auto get_return_r() { return ReturnR{TargetType{}}.return_r(); } // 包装后让调用更接近需求 auto return_r() { return [](auto&& func) { using ArgType = std::remove_reference_t<typename std::function_traits<decltype(func)>::argument_type>; func(get_return_r<ArgType>()); }; } void accep_float(float arg) { std::cout << "收到float参数: " << arg << "\n"; } int main() { return_r()(accep_float); // 调用方式稍作调整,实现自动推导 }
这个方案严格贴合了你对模板推导指引的需求,不过相比方案1会复杂一些,适合需要明确使用模板推导机制的场景。
关键说明
C++标准本身不支持从函数参数的目标类型反向推导函数模板的返回值参数(也就是所谓的"反向推导"),所以我们要么用代理类的隐式转换绕过推导,要么用类模板推导指引配合辅助函数来实现上下文推导。
内容的提问来源于stack exchange,提问作者asmmo
相关产品推荐
相关产品推荐

