是否存在通用方法可将任意C++重载函数包装为函数对象?
回答
C++中重载函数名本身不是可直接传递的一等实体,目前兼容性最好的通用方案基于宏实现,能够完整保留原函数的所有行为特性:
// C++20及以上版本通用封装宏 #define WRAP_OVERLOAD(Func) \ []<typename... Args>(Args&&... args) \ noexcept(noexcept(Func(std::forward<Args>(args)...))) \ -> decltype(auto) \ { \ return Func(std::forward<Args>(args)...); \ }
该宏生成的泛型lambda会完美转发所有参数、继承原函数的noexcept限定符、返回值类型,同时完整保留原函数的SFINAE约束,不会额外引入限制。
针对你给出的compose场景,直接用宏即可一行完成封装,和手动实现的函数对象行为完全一致:
namespace functors { inline constexpr auto compose = WRAP_OVERLOAD(::compose); }
如果需要兼容C++17,可以使用模板函数对象版本,该版本适合可明确获取重载函数地址的场景:
template <auto Func> struct OverloadWrapper { template <typename... Args> constexpr decltype(auto) operator()(Args&&... args) const noexcept(noexcept(Func(std::forward<Args>(args)...))) { return Func(std::forward<Args>(args)...); } }; #define WRAP_OVERLOAD_CPP17(Func) OverloadWrapper<Func>{}
上述两种方案生成的包装对象都完全符合你提到的三个优势:可直接作为高阶函数参数传递、不受ADL规则干扰、调用时不需要显式指定模板参数。
内容的提问来源于stack exchange,提问作者Desmond Gold
相关产品推荐
相关产品推荐

