我确信这可以做到,因为它可以用c宏完成,但不能用语法包围我的脑袋。或者如果它甚至可能。
假设我有B类和C类,都实现了函数foo(int),都继承了A,但是当我调用我的帮助器时我不想知道类型(比如我用enum类型调用,就像这样:
我一直在思考,但无法获得最后的接触:
#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;
}
甚至可能吗? 提示?对问题名称提出建议:)
答案 0 :(得分:2)
您可以通过函数模板调用具有相同名称的无关类的成员函数:
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)...);
}
}
答案 1 :(得分:0)
这是不可能的,因为activate
重载int type
只传递一个成员函数指针,但需要转发到另一个activate
重载与另一个成员每种支持类型的函数指针(即&B::test
或&C::test
)。
答案 2 :(得分:0)
编译方法 activate
(忘记一秒的返回类型)将不起作用,因为只有一个切换选项调用正确的激活重载,而所有其他选项包含{{1对于return static_cast<X&>(parent)
与A *child = new Y;
不同的任何语句Y
无效。
以下是我理解你要做的事情;你有一堆课程,说X
... B1
来自一个班级Bn
。所有A
都实现了一个方法Bi
,其中所有T foo( ... )
的输出和输入都相同,但i
没有实现此方法。您希望以通用方式为A
存储Bi
,因此您自然会编写i
,但之后您想知道如何调用适当的方法A *child = new Bi
。
有几种方法可以做到这一点。由于方法foo始终具有相同的原型,最简单的方法可能是在foo
中将foo
声明为虚拟或纯虚拟。
如果您不想使用虚拟,那么您可以使用类似
的内容A
您可以在函数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)... ); }
中使用的。