在设置函数指针之前绑定参数?

发布于 2024-11-29 03:19:17 字数 699 浏览 4 评论 0原文

我想尝试一些东西,并在我们的动态库 API 包装器之一中统一一些样板代码。

本质上,我想做以下事情:

typedef bool (*MyFPtrT)(long id, std::string const& name);
typedef boost::function<bool (long id, std::string const& name)> MyFObjT;
...

...
  MyFPtrT pDllFun = NULL;
  long x = 42; string s = "Answer"; // API input, not hardcoded
  MyFObjT f = boost::bind(pDllFun, x, s);
  ...
  return Call(f);
...

template<FT>
bool Call(FT f) {
  ...
  MyFPtrT pDllFun = (MyFunPtr)::GetProcAddress(...);
  f.setFunctionPointerButLeaveBoundParameters(pDllFun); // <- how??
  // Now call the correctly rigged up function object:
  return f();
}

这可能吗? (使用Boost还是其他?)(C++03

I would like to try something out and unify some boilerplate code in one of our dynamic library API wrappers.

Essentially, I would like to do the following:

typedef bool (*MyFPtrT)(long id, std::string const& name);
typedef boost::function<bool (long id, std::string const& name)> MyFObjT;
...

...
  MyFPtrT pDllFun = NULL;
  long x = 42; string s = "Answer"; // API input, not hardcoded
  MyFObjT f = boost::bind(pDllFun, x, s);
  ...
  return Call(f);
...

template<FT>
bool Call(FT f) {
  ...
  MyFPtrT pDllFun = (MyFunPtr)::GetProcAddress(...);
  f.setFunctionPointerButLeaveBoundParameters(pDllFun); // <- how??
  // Now call the correctly rigged up function object:
  return f();
}

Is this possible? (With Boost or otherwise?) (C++03)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

疏忽 2024-12-06 03:19:17

我认为不能直接这样做,因为 bind 创建一个新对象,该对象通过引用获取函数对象和参数,并且您无法重新绑定引用。

但是,您可以轻松地使用可重新分配的函数指针编写自己的模板化仿函数包装器:

template <typename R, typename A, typename B>
struct ReAssFunctor
{
  typedef R(*FP)(A, B);

  ReAssFunctor(const A & a_, const B & b_) a(a_), b(b_) { }

  R operator()() const { return func(a, b); }

  FP function;

private:
  const A & a;
  const B & b;
};

[编辑:] 请检查下面的注释;在构造函数中保存 const 引用所采用的引用可能会被危险地滥用,因此请小心,或者如果您愿意,可以按值保存 ab。[/]

现在您可以初始化尽早使用参数的仿函数:

ReAssFunctor<R, A, B> raf(a, b);

然后分配一个函数指针并调用:

raf.function = foo;
raf();

raf.function = goo;
raf();

您甚至可以用以下方式替换调用运算符:

  template <typename U>
  U operator()(U (f*)(A, B)) const { return f(a, b); }

然后使用函数指针作为参数调用仿函数:

raf(fp1);  // calls fp1(a,b);
raf(fp2);  // calls fp2(a,b);

在这种情况下,您不需要返回类型为不再是固定参数,但现在你得不到无效调用运算符。任你挑选。

I don't think it can be done directly like that, because bind creates a new object that takes the function object and the arguments by reference, and you can't rebind references.

However, you can easily enough write your own templated functor wrapper with a reassignable function pointer:

template <typename R, typename A, typename B>
struct ReAssFunctor
{
  typedef R(*FP)(A, B);

  ReAssFunctor(const A & a_, const B & b_) a(a_), b(b_) { }

  R operator()() const { return func(a, b); }

  FP function;

private:
  const A & a;
  const B & b;
};

[Edit:] Do check the comments below; holding references taken by const reference in the constructor can be dangerously abused, so be careful, or save a and b by value if you prefer.[/]

Now you can initialize the functor with the arguments early:

ReAssFunctor<R, A, B> raf(a, b);

Then assign a function pointer and call:

raf.function = foo;
raf();

raf.function = goo;
raf();

You could even replace the call operator by this:

  template <typename U>
  U operator()(U (f*)(A, B)) const { return f(a, b); }

And then invoke the functor with the function pointer as the argument:

raf(fp1);  // calls fp1(a,b);
raf(fp2);  // calls fp2(a,b);

In that case you don't need the return type as a fixed parameter any longer, but now you don't get a nullary call operator. Take your pick.

喜爱纠缠 2024-12-06 03:19:17

似乎以下内容可能有效:

typedef bool (*MyFPtrT)(long id, std::string const& name);
typedef boost::function<bool (long id, std::string const& name)> MyFObjT;
...

...
  MyFPtrT pDllFun = NULL;
  long x = 42; string s = "Answer"; // API input, not hardcoded
  MyFObjT f = boost::bind(boost::ref(pDllFun), x, s);
  ...
  return Call(f, pDllFun);
...

template<class FT, class FP>
bool Call(FT f, FP& pDllFun) {
  pDllFun = (MyFunPtr)::GetProcAddress(...);
  return f();
}

是的,那里有一些危险的参考资料。特别是,f 保留对 pDllFun 的引用。这可以很容易地缓解:将两者打包在一个类中,因此生命周期显然是相同的。

Seems the following might work:

typedef bool (*MyFPtrT)(long id, std::string const& name);
typedef boost::function<bool (long id, std::string const& name)> MyFObjT;
...

...
  MyFPtrT pDllFun = NULL;
  long x = 42; string s = "Answer"; // API input, not hardcoded
  MyFObjT f = boost::bind(boost::ref(pDllFun), x, s);
  ...
  return Call(f, pDllFun);
...

template<class FT, class FP>
bool Call(FT f, FP& pDllFun) {
  pDllFun = (MyFunPtr)::GetProcAddress(...);
  return f();
}

Yeah, there are some dangerous references around there. In particular, f keeps a reference to pDllFun. This can be mitigated fairly easy: pack the two in a single class, so the lifetimes are obviously identical.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文