gpt4 book ai didi

c++ - 使用 boost::function::target 获取函数指针时的空指针

转载 作者:行者123 更新时间:2023-11-30 03:12:12 24 4
gpt4 key购买 nike

看完this answer我以为我有解决办法。至少答案是我想做的,但我在实现时遇到了问题。

这是我正在尝试做的事情的概述

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 可能无法执行运行时转换。有什么想法吗?

最佳答案

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

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

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

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

对于函数指针,这非常有效,因为您知道分配给 boost::function 对象的函数类型。但是对于复杂的可调用对象,它就不再适用了。

为了能够看到它的工作并看到它不仅可以使用函数指针,还可以使用绑定(bind)表达式,请考虑以下代码

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 的文章 Conditional Love看看这个代码片段是如何工作的。

关于c++ - 使用 boost::function::target 获取函数指针时的空指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1381042/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com