Templateed helper函数,用于调用具有特定函数的特定模板化子级

Templated helper Functions to call specific templated children with specific function

本文关键字:函数 helper 用于 调用 Templateed      更新时间:2023-10-16

我确信这是可以做到的,因为它可能可以用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;
}

这可能吗?提示?接受问题名称的建议:)

您可以通过函数模板调用与不相关类同名的成员函数:

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函数模板仍然需要计算返回类型。有几种选择,所有这些都有缺点:

  1. 使用第一种情况的返回类型
  2. 为所有案例查找通用类型
  3. 从外部提供返回类型

由于最后一个可能是最简单的,我现在就用它。呼叫变为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)...);
}
}

现场演示

这是不可能的,因为采用int typeactivate重载只传递了一个成员函数指针,但需要针对每种支持的类型(即&B::test&C::test)使用不同的成员函数指针转发给另一个activate重载。

编译方法activate(暂时忘记返回类型)将不起作用,因为只有一个开关选项调用了正确的activate重载,而所有其他选项都包括一个return static_cast<X&>(parent),该CCD_9对于A *child = new Y;的任何语句都无效,YX不同

以下是我如何理解你的意图;你有很多课,比如B1。。。14,其从类别CCD_。所有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)... ); }

可以在函数CCD_ 26中使用。