C++万能引用解析:为何装饰器适配Lambda却不适配函数指针?
问题根源
你遇到的问题核心是重载函数名无法直接参与模板参数推导。
当你传递func2给decorator的auto&& function参数时,func2是两个重载函数的名字,编译器需要先确定function的具体类型才能完成推导,但此时没有足够的上下文让编译器判断该选择哪个func2重载版本——模板参数推导是独立于后续的函数调用匹配的,编译器不会先看后面的参数a,7,6来反推func2的类型。
而Lambda能正常编译是因为Lambda表达式是一个唯一的闭包类型,不存在重载,编译器可以直接推导其类型,自然能正常转发调用。
解决方案
有两种直接的解决方式:
1. 显式指定重载版本(最直接)
通过强制类型转换,告诉编译器要选择哪个func2重载:
// 选择接收const A&的重载 decorator(static_cast<int(*)(const A&, int, int)>(func2), a, 7, 6); // 或者如果要调用接收A&&的重载,传临时对象并转换对应类型 decorator(static_cast<int(*)(A&&, int, int)>(func2), A(), 7, 6);
2. 使用辅助模板包装重载函数
如果你不想每次都写强制转换,可以写一个小模板来帮助编译器推导:
template<typename... Args> auto pick_overload(int(*func)(Args...)) { return func; }
然后这样调用:
// 编译器会根据后面的参数推导Args为const A&, int, int decorator(pick_overload(func2), a, 7, 6);
补充说明
你的decorator里的万能引用(auto&& function和auto&&... params)本身是正确的,转发逻辑也没问题——问题出在重载函数名无法被模板推导识别,和万能引用的转发机制无关。
内容的提问来源于stack exchange,提问作者buridan
相关产品推荐
相关产品推荐

