使用boost :: function :: target获取函数指针时的空指针 [英] null pointer when getting function pointer using boost::function::target

查看:353
本文介绍了使用boost :: function :: target获取函数指针时的空指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读此答案后以为我有一个解决方案。至少答案是我想做的,但我有一个问题的实现。

After reading this answer I thought I had a solution. At least the answer there is what I would like to do but I'm having a problem with the implementation.

这里是我想做的一个大纲

here is an outline of what I am trying to do

typedef map<string, double*> myMap;
typedef int (*ftwpt)(const char*, const struct stat*, int);
typedef boost::function<int(const char*, const struct stat*, int)> MyFTWFunction;

int myFunction(const char*, const struct stat*, int, myMap*);

int main()
{
myMap m_map;
char tmpdir[] = "/tmp/mytmp";

MyFTWFunction f = boost::bind(myFunction,_1,_2,_3, &m_map);

ftwpt* fpt = f.target<ftwpt>();
if (fpt)
    status = ftw(tmpdir, *fpt, 50);
else
{
    cout << "Boost could not perform runtime conversion on function pointer" << endl;
    return (EXIT_FAILURE);
}
}

程序编译时没有错误或警告,获取从f.target()返回的空指针(fpt);在运行时。从上面的stackoverflow问题链接的引用,如果boost无法执行运行时转换,似乎将返回一个空指针。但我不知道为什么Boost可能无法执行运行时转换。任何想法?

the program compiles with no errors or warnings but I am getting a null pointer (fpt) returned from f.target(); at runtime. From references linked on the above stackoverflow question it seems a null pointer is returned if boost is unable to perform the runtime conversion. But I have no idea why Boost might not be able to perform the runtime conversion. Any ideas?

推荐答案

为了工作,你需要知道绑定表达式的确切类型, boost :: function 对象。对象 boost :: bind(....)返回是一些奇怪的表达式模板,而不是函数指针。

For that to work, you would need to know the exact type of the bind expression that you store into the boost::function object. The object boost::bind(....) returns is some weird expression template, not a function pointer.

为了理解为什么需要这样做,请考虑如何在原理上实现boost :: function。

To understand why this is needed, consider how boost::function is implemented in principle

struct base { virtual ~base() { } };

template<typename T>
struct derived : base {
  derived(T t):t(t) { }
  T t;
};

struct function {
  template<typename T>
  function(T t) {
    base *b = new derived<T>(t);
  }

  template<typename T>
  T *target() {
    if(typeid(*b) == typeid(derived<T>))
      return &static_cast< derived<T>* >(b)->t;
    return 0;
  }

  base *b;
};

这是最基本的结构,没有 $ c> bloat - 很像 boost :: any 。该机制称为类型擦除:构造函数接受任意类型的对象,然后将对象封装到一个对象中,您可以通过虚拟函数调用( boost :: function 像地狱一样优化,使用自己的vtable和堆栈分配来避免 new 用于小类型等等)。

That's the most fundamental structure, without the operator() bloat - much like boost::any. The mechanism is called type-erasure: The constructor accepts objects of arbitrary types, and then stores an object encapsulated into an object that you may reach through virtual function calls (boost::function is optimized like hell, using its own vtable and stack-allocation to avoid new for small types and so on).

对于函数指针,这很好,因为你知道分配给 boost :: function object。但对于复杂的可调用对象,它不再工作了。

For function pointers, this works great, because you know the type of the function that you assign to the boost::function object. But for complex callable objects, it doesn't quite work anymore.

为了能够看到它的工作,看到它不只是使用函数指针,而且使用绑定表达式,请考虑以下代码

To be able to see it working and to see that it's not just working with function pointers, but also with bind expressions, consider the following code

template<typename T>
struct id { typedef T type; };

template<typename T>
id<T> make_id(T) { return id<T>(); }

struct any_type {
  template<typename T>
  operator id<T>() const { return id<T>(); }
};

template<typename T, typename Fn>
T *get_target(boost::function<Fn> &f, id<T>)
{ return f.template target<T>(); }

void f(int a, int b) { std::cout << a << " " << b << std::endl; }

int main() {
  boost::function<void(int)> g = boost::bind(&f, _1, 10);
  (*get_target(g, true ? any_type() : make_id(boost::bind(&f, _1, 10))))(2);
}

get_target 知道 boost :: bind 返回的类型。你可以使用它来调用 target 调用并返回包装在 boost :: function 中的对象。在 main 中,我们调用bind表达式。请阅读Eric Niebler的文章有条件的爱,了解此代码段的工作原理。

Within get_target you know the type of what boost::bind returns. You can use that to call the target call and return the object that's wrapped inside the boost::function. Within main we then call the bind expression. Please read Eric Niebler's article Conditional Love to see how this code snippet works.

这篇关于使用boost :: function :: target获取函数指针时的空指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆