【问题标题】:functor generation from member function pointer type从成员函数指针类型生成函子
【发布时间】:2009-10-10 18:23:07
【问题描述】:

我正在尝试简化(通过make_fn())为arity n的成员函数预处理参数(通过wrap())的仿函数的生成。
生成仿函数基本上是可行的,但直到现在只能通过显式指定成员函数的参数类型。
现在我想从它处理的成员函数类型生成正确的仿函数:

struct X {};

template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
bool wrap(C* c, X x) 
{
    return (c->*F)(process<T1>(x));
}

template<class C, typename T1, bool (C::*F)(T1)> 
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(F f) // <- problem here, F is not a type
{
    return boost::bind(&wrap<C, T1, F>, _1, _2);
}

但是,有了这个,vc++ 和 g++ 不会将F 视为make_fn() 参数的类型。我必须在这里错过一些明显的东西,并且感觉有点盲目。

这个想法是它应该像这样工作:

struct A 
{
    bool f1(bool) { return true; }
};

void test()
{
    A a;
    X x;
    make_fn(&A::f1)(&a, x);
}

关于如何实现它的任何想法?

背景:
我有一个固定的界面,简化后看起来像这样:

bool invoke(C* c, const char* const functionName, int argCount, X* args);

X 是一种变体类型,我必须将其转换为某些后端类型(int、std::string、...)。
为了处理这些调用,我有一个按名称查找的仿函数映射,并将这些调用映射到某个实例的成员函数。
包装的目的是避免手动转换,而是生成为我或throw 进行转换的函子。我有这个使用基于宏的解决方案,但该解决方案需要明确指定类型和参数计数。
通过函数重载解析,我希望从成员函数签名中隐式生成正确的转换函子。

【问题讨论】:

  • 您真正想要实现的目标是什么?你想从 bind (boost/c++0x) 中简化什么?似乎您想要的是一个模板,该模板接受一个作为成员函数指针的参数并创建一个函子,该函子需要一个实例和适当数量的参数而无需用户干预(即,无需用户制作参数编号/显式类型,是这样吗?
  • 是的,基本上我想要一个具有固定数量参数的函子,它包装了 arity n 的成员函数和任意类型。
  • 在我看来,您希望对非类型参数进行模板推导。 F 不是一种类型:它是一个指向特定成员函数的指针,因此您不能使用make_fn(F f)。我不确定它是否会成功:您似乎想从运行时成员函数指针变量构造一个模板。
  • 但是一个成员函数有一个类型/签名,我也应该能够从中扣除?扣除应该在编译时发生。 Boost bind 似乎做了类似的事情,但至于它们广泛的实现细节,我看不出他们是如何解决的。
  • boost 是否真的使用非类型模板参数?想象一下:bool (X::*mp)(Y) = rand() % 2 ? &amp;X::foo : &amp;X::bar; make_fn(mp); 你到底希望发生什么?

标签: c++ templates functor


【解决方案1】:

在我看来,您正试图将传递给函数的指针转换为非类型模板参数,恐怕这不会起作用(请参阅 cmets 您的问题)。

您可以做的是将函数指针存储在函数对象中。以下似乎可以编译:

#include <boost/bind.hpp>
#include <boost/function.hpp>

struct X {};

template <class T>
bool process(X) { return true; }


template <class C, class T1, class Func>
struct wrap1
{
    typedef bool result_type;
    Func f;

    wrap1(Func f): f(f) {}

    bool operator()(C* c, X x)
    {
        return (c->*f)(process<T1>(x));
    }
};

template<class C, typename T1>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(bool (C::*f)(T1))
{
    return boost::bind(wrap1<C, T1, bool (C::*)(T1)>(f), _1, _2);
}


struct A
{
    bool f1(bool) { return true; }
};

void test()
{
    A a;
    X x;
    make_fn(&A::f1)(&a, x);
}

但是,我不确定这是否有任何好处,以及您将如何创建其余的包装器。对于后者,您可能会得到一个支持可变参数模板的编译器。 :)

【讨论】:

  • 虽然我曾希望避免生成另一个仿函数,但这是可行的 - 谢谢 :) 对于伪变量模板(我在 vc8 中需要它),可以为所有需要的 arities 定义 make_fn()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多