繁体   English   中英

模板化辅助函数调用具有特定功能的特定模板化子级

[英]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功能模板仍需要弄清楚返回类型。 有几种选择,所有这些都有缺点:

  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)...);
    }
}

现场演示

这是不可能的,因为呈现的,因为activate过载取int type仅通过单一的成员函数的指针,但需要转发到另一个activate过载有用于每个支持的类型不同的成员函数的指针(即,或者&B::test&C::test )。

编译您的activate方法(忽略返回类型一秒钟)将无法正常工作,因为只有一个开关选项调用了正确的激活重载,而所有其他选项都包含一个return static_cast<X&>(parent) ,该返回值对于任何其他选项均无效陈述A *child = new Y; YX

这是我对您正在尝试做的事情的理解; 您有一堆从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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM