std::function
是 C++ 标准库中的一个模板类,用于封装任何可调用实体(如函数、函数指针、函数对象等),并允许它们以统一的方式被调用。然而,有时我们可能需要一种更灵活的方式来处理不同参数和返回类型的可调用实体。
为了实现这一目标,C++ 提供了模板和类型擦除的技术。通过模板,我们可以编写能够处理多种类型的代码,而类型擦除则允许我们在运行时处理不同类型的对象,同时保持接口的一致性。
与 std::function
类似但更灵活的类型通常是通过模板和类型擦除技术自定义实现的。例如,可以创建一个 AnyCallable
类模板,它可以封装任何可调用实体,并允许在运行时指定参数和返回类型。
以下是一个简单的 AnyCallable
类模板的实现示例,它允许封装和调用具有不同参数和返回类型的可调用实体:
#include <iostream>
#include <type_traits>
#include <utility>
template<typename R, typename... Args>
class AnyCallable {
public:
virtual ~AnyCallable() = default;
virtual R invoke(Args... args) = 0;
};
template<typename F, typename R, typename... Args>
class CallableWrapper : public AnyCallable<R, Args...> {
public:
CallableWrapper(F&& func) : func_(std::forward<F>(func)) {}
R invoke(Args... args) override {
return func_(std::forward<Args>(args)...);
}
private:
F func_;
};
template<typename R, typename... Args>
AnyCallable<R, Args...>* makeAnyCallable(R(*func)(Args...)) {
return new CallableWrapper<decltype(func), R, Args...>(func);
}
template<typename F, typename R, typename... Args>
AnyCallable<R, Args...>* makeAnyCallable(F&& func) {
return new CallableWrapper<F, R, Args...>(std::forward<F>(func));
}
// 示例用法
int add(int a, int b) {
return a + b;
}
double multiply(double a, double b) {
return a * b;
}
int main() {
auto addCallable = makeAnyCallable(add);
auto multiplyCallable = makeAnyCallable(multiply);
std::cout << "Add: " << addCallable->invoke(3, 4) << std::endl;
std::cout << "Multiply: " << multiplyCallable->invoke(3.5, 2.0) << std::endl;
delete addCallable;
delete multiplyCallable;
return 0;
}
问题:在实现自定义的可调用实体类型时,可能会遇到类型擦除带来的性能开销。
解决方法:
std::any
或类似技术来存储和恢复可调用实体的状态时,要注意其性能开销。通过合理的设计和优化,可以在保持灵活性的同时,尽量减少性能损失。
领取专属 10元无门槛券
手把手带您无忧上云