C++ std::函数中参数的自动动态_强制转换
我们有多态类A和B,如:C++ std::函数中参数的自动动态_强制转换,c++,C++,我们有多态类A和B,如: struct A { virtual ~A() {} }; struct B final : public A { void f() { std::cout << "f" << std::endl; } }; 有没有什么方法可以在不使用[](A*A){}包装内部函数的情况下自动实现这一点?我的目标是使以下语法正常工作: std::function<void(A*)> funcA = dynStdFunc([](B*
struct A {
virtual ~A() {}
};
struct B final : public A {
void f() { std::cout << "f" << std::endl; }
};
有没有什么方法可以在不使用
[](A*A){}
包装内部函数的情况下自动实现这一点?我的目标是使以下语法正常工作:
std::function<void(A*)> funcA = dynStdFunc([](B* b) { b->f(); });
它接受functionoid类型,并返回一个包含其参数类型的pack
。太好了
2.std::function所需的参数在
dynStdFunc
内部是未知的。我们实现这一点的方法是返回一个临时对象,其中包含一个模板,用于将运算符转换为std::function
.为了清楚起见,
{b->f();}
是使用b
的整个函数体的占位符,对吗?@Quentin对。这似乎是一个非常做作的示例。你能详细说明一下你想用这个解决方案解决的实际问题吗?f()
不应该是虚拟的,这样你就可以从A
实例中调用它了吗?在那种情况下,没有铸造。我可以解决这个问题,但我不想。因为您可能会使用我的解决方案代码>将允许同时使用动态强制转换指针和非强制转换参数。还允许外包装是[](自动&&…->decltype(自动)
,而不是在std::function
@Yakk的类型上进行匹配。astd::function
可以调用泛型functor吗?@Yakk oooh。这是一个戈德堡级的滥杀滥伤。
std::function<void(A*)> funcA = dynStdFunc([](B* b) { b->f(); });
// C++17's void_t
template <class...>
using void_t = void;
// Pack of arbitrary types
template <class...>
struct pack { };
namespace detail_parameters {
template <class F, class = void_t<>>
struct parameters { };
template <class F>
struct parameters<F, void_t<decltype(&F::operator ())>>
: parameters<decltype(&F::operator ())> { };
template <class R, class... Params>
struct parameters<R(Params...)> { using type = pack<Params...>; };
// More specializations for functions, function pointers,
// member function pointers...
}
// Retrieve the parameter list from a functionoid
template <class F>
using parameters = typename detail_parameters::parameters<std::remove_reference_t<F>>::type;
namespace detail_dynStdFunc {
// F = functionoid, Ps = pack of its parameters
template <class F, class Ps>
struct wrapper;
template <class F, class... Ps>
struct wrapper<F, pack<Ps...>> {
template <class Ret, class... Args>
operator std::function<Ret(Args...)> () {
// Now we know what parameters the `std::function` needs
}
F f;
};
}
template <class F>
auto dynStdFunc(F &&f) {
return detail_dynStdFunc::wrapper<
std::remove_reference_t<F>,
parameters<F>
>{std::forward<F>(f)};
}
template <class Ret, class... Args>
operator std::function<Ret(Args...)> () {
return [f_ = std::move(f)](Args... args) -> Ret {
return f_(dynamic_cast<Ps>(args)...);
};
}
template <class F, class... Ps>
auto dynStdFunc(F &&f, pack<Ps...>) {
return [f_ = std::forward<F>(f)](auto *... args) -> decltype(auto) {
return f_(dynamic_cast<Ps>(args)...);
};
}
template <class F>
auto dynStdFunc(F &&f) {
return dynStdFunc(std::forward<F>(f), parameters<F>{});
}