C回调到功能模板:显式实例化模板 [英] C-callback to function template: explicitly instantiate template

查看:156
本文介绍了C回调到功能模板:显式实例化模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用C库(来自C ++),该库提供以下接口:

I’m using a C library (from C++) which provides the following interface:

void register_callback(void* f, void* data);
void invoke_callback();

问题

现在,我需要注册一个函数模板作为回调,这给我带来了问题.考虑以下代码:

Problem

Now, I need to register a function template as a callback and this is causing me problems. Consider the following code:

template <typename T> void my_callback(void* data) { … }

int main() {
    int ft = 42;
    register_callback(reinterpret_cast<void*>(&my_callback<int>), &ft);
    invoke_callback();
}

这给了我以下链接器错误(在OS X上使用g ++(GCC)4.5.1 ,但可以在大多数其他编译器版本/平台组合上使用):

This gives me the following linker error (using g++ (GCC) 4.5.1 on OS X but works on most other combinations of compiler version / platform):

x86_64体系结构的未定义符号:

Undefined symbols for architecture x86_64:

"void my_callback<int>(void*)", referenced from:  
  _main in ccYLXc5w.o

我认为是可以理解的.

可以通过显式实例化模板来轻松解决此问题:

This is easily fixed by explicitly instantiating the template:

template void my_callback<int>(void* data);

不幸的是,这不适用于我的真实代码,因为回调是在函数模板内注册的.我不能为所有它们提供显式的实例化(我正在编写一个库).所以我的真实代码看起来像这样:

Unfortunately, this isn’t applicable in my real code since the callback is registered inside a function template, and I don’t know for which set of template arguments this function will be called, so I can’t provide explicit instantiations for all of them (I’m programming a library). So my real code looks a bit like this:

template <typename T>
void do_register_callback(T& value) {
    register_callback(reinterpret_cast<void*>(my_callback<T>), &value);
    // Other things …
}

int main() {
    int ft = 42;
    do_register_callback(ft);
    invoke_callback();
}

第二个解决方案"

通过调用函数隐式实例化函数模板.因此,让我们这样做,但请确保该呼叫实际上并未执行(该功能有副作用):

Second "solution"

A function template is implicitly instantiated by calling the function. So let’s do that, but make sure that the call isn’t actually performed (the function has got side-effects):

template <typename T>
void do_register_callback(T& value) {
    if (false) { my_callback<T>(0); }
    register_callback(reinterpret_cast<void*>(my_callback<T>), &value);
}

即使启用了优化,此似乎也可以工作(这样,死分支将被编译器删除).但是我不确定这一天是否会结束.我还发现这是一个非常丑陋的解决方案,需要冗长的解释性注释,以免将来的维护者删除此明显不必要的代码.

This seems to work, even with optimisations enabled (so that the dead branch is removed by the compiler). But I’m not sure if this won’t some day break down. I also find this a very ugly solution that requires a length explanatory comment lest some future maintainer remove this obviously unnecessary code.

如何实例化一个我不知道其模板参数的模板?这个问题显然是胡说:我不能. –但是这有偷偷摸摸的方法吗?

How do I instantiate a template for which I don’t know the template arguments? This question is obviously nonsense: I can’t. – But is there a sneaky way around this?

除非,我的解决方法是否一定能成功?

代码(特别是我将函数指针转换为void*的事实)也会产生以下警告:

The code (specifically, the fact that I cast a function pointer to void*) also produces the following warning:

ISO C ++禁止在指针指向函数和指针指向对象之间进行强制转换

ISO C++ forbids casting between pointer-to-function and pointer-to-object

当使用-pedantic进行编译时.我可以以某种方式摆脱警告,而不必为该库编写一个强类型的C包装器(在我的情况下这是不可能的)吗?

when compiling with -pedantic. Can I somehow get rid of the warning, without writing a strongly-typed C wrapper for the library (which is impossible in my situation)?

在ideone上运行代码 (并添加了强制转换以使其可编译)

Running code on ideone (with an added cast to make it compile)

推荐答案

POSIX建议采用以下方法在函数指针类型和对象指针类型(在C99中未定义)之间进行转换:

POSIX recommends the following way to cast between function pointer types and object pointer types (which is undefined in C99):

typedef void function_type(void*);
function_type *p_to_function = &my_callback<T>;
void* p_to_data = *(void**)&p_to_function;

// Undefined:
// void* p_to_data = (void*)p_to_function;

请注意,在C ++领域,这将从function_type**执行reinterpret_cast<void**>(&p_to_function).与reinterpret_cast<void*>(p_to_function)不同,这不是不确定的,而是实现定义的.因此,编写依赖于实现的符合C ++的代码可能是最好的选择.

Notice that in C++-land, this would perform a reinterpret_cast<void**>(&p_to_function) from function_type**. This is not undefined but instead implementation-defined, unlike reinterpret_cast<void*>(p_to_function). So it's probably your best bet to write C++-conformant code that relies on the implementation.

这篇关于C回调到功能模板:显式实例化模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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