[英]Templated helper Functions to call specific templated children with specific function
我确信这是可以做到的,因为它可能可以使用ac宏来完成,但是我无法将头放在语法上。 甚至有可能。
假设我有B类和C类,都实现了函数foo(int),都继承了A,但是当我调用助手时,我不想知道类型(例如,我用枚举类型调用,如下所示:
我一直在思考,但是无法获得最终的效果:
#include <iostream>
#include <memory>
using namespace std;
struct A {};
template< typename R, typename C, typename... Args > R member_func(R (C::*)(Args...));
template<typename Child_t, typename Child_t::* func, typename ...Args_t>
auto activate(A& parent, Args_t... args) -> decltype(member_func(Child_t::func)) { return static_cast<Child_t&>(parent).*func(forward<Args_t>(args)...); }
template<typename (???)::* func, typename ...Args_t>
auto activate(int type, A& parent, Args_t... args) -> decltype(??? they would both return the same thing) {
switch (type) {
case 0: return activate<B>(parent, forward<Args_t>(args)...);
case 1: return activate<C>(parent, forward<Args_t>(args)...);
}
}
struct B : public A { int test(int i) { return i; } };
struct C : public A { int test(int i) { return i+1; } };
void foo() {
int type = 0;
A* child = new B;
cout << activate(type, *child, ??test??, 4) << endl;
}
可能吗? 提示? 提出关于问题名称的建议:)
您可以通过函数模板调用具有相同名称的不相关类的成员函数:
template<typename O, typename... Args>
auto test(O&& o, Args&&... args)
-> decltype( std::forward<O>(o).test(std::forward<Args>(args)...) )
{
return std::forward<O>(o).test(std::forward<Args>(args)...);
}
函数模板(如重载集)不能直接作为参数传递给另一个函数。 解决该问题的常见方法是将它们包装在函数对象类型中:
struct test_wrapper
{
template<typename O, typename... Args>
auto operator()(O&& o, Args&&... args)
-> decltype( std::forward<O>(o).test(std::forward<Args>(args)...) )
{
return std::forward<O>(o).test(std::forward<Args>(args)...);
}
};
我们的目标是通过以下方式编写呼叫:
activate(type, *child, test_wrapper{}, 4)
OP的activate
功能模板仍需要弄清楚返回类型。 有几种选择,所有这些都有缺点:
由于最后一个可能是最简单的,因此我现在将使用它。 调用变为activate<int>(type, *child, test_wrapper{}, 4)
template<typename Child_t, typename A, typename F, typename ...Args_t>
auto activate(A& parent, F f, Args_t... args)
-> decltype( f(static_cast<Child_t&>(parent), std::forward<Args_t>(args)...) )
{ return f(static_cast<Child_t&>(parent), std::forward<Args_t>(args)...); }
template<typename Ret, typename A, typename F, typename ...Args_t>
Ret activate(int type, A& parent, F f, Args_t... args) {
switch (type) {
case 0: return activate<B>(parent, f, std::forward<Args_t>(args)...);
case 1: return activate<C>(parent, f, std::forward<Args_t>(args)...);
}
}
这是不可能的,因为呈现的,因为activate
过载取int type
仅通过单一的成员函数的指针,但需要转发到另一个activate
过载有用于每个支持的类型不同的成员函数的指针(即,或者&B::test
或&C::test
)。
编译您的activate
方法(忽略返回类型一秒钟)将无法正常工作,因为只有一个开关选项调用了正确的激活重载,而所有其他选项都包含一个return static_cast<X&>(parent)
,该返回值对于任何其他选项均无效陈述A *child = new Y;
Y
与X
。
这是我对您正在尝试做的事情的理解; 您有一堆从A
类派生的类,例如B1
... Bn
。 所有Bi
实现了方法T foo( ... )
,其中所有i
的输出和输入都相同,但是A
没有实现此方法。 您想为任何i
存储Bi
的通用方法,因此您自然会编写A *child = new Bi
,但是您想知道如何调用适当的方法foo
。
有几种方法可以做到这一点。 由于方法foo始终具有相同的原型,因此最简单的方法可能是在A
中将foo
声明为虚拟或纯虚拟。
如果您不想使用虚拟,则可以使用类似
template <class T, class... Args>
typename std::result_of< decltype( &T::foo( Args... ) )(T) >::type
call_foo( T& X, Args... args )
{ return X.foo( std::forward<Args>(args)... ); }
您可能会在功能中使用它activate
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.