相关疑难解决方法(0)

C回调函数模板:显式实例化模板

前提

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

void register_callback(void* f, void* data);
void invoke_callback();
Run Code Online (Sandbox Code Playgroud)

问题

现在,我需要注册一个函数模板作为回调,这导致我的问题.请考虑以下代码:

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

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

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

架构x86_64的未定义符号:

"void my_callback<int>(void*)", referenced from:  
  _main in ccYLXc5w.o
Run Code Online (Sandbox Code Playgroud)

我觉得这是可以理解的.

首个"解决方案"

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

template void my_callback<int>(void* data);
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不适用于我的真实代码,因为回调是函数模板中注册的,我不知道这个函数将被调用哪个模板参数集,因此我不能为所有的函数提供显式实例化.他们(我正在编写一个图书馆).所以我的真实代码看起来有点像这样:

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();
}
Run Code Online (Sandbox Code Playgroud)

第二"解决方案"

通过调用函数隐式实例化函数模板.所以我们这样做,但要确保调用没有实际执行(该函数有副作用): …

c++ macos templates undefined-reference gcc4

14
推荐指数
3
解决办法
2705
查看次数

在获取地址时隐式实例化功能模板

注意:我已经看过这里,我认为答案是对的.

在获取地址时,管理函数隐式实例化的规则是什么?n3242的14.7.1/9说:

实现不应隐式实例化函数模板,成员模板,非虚拟成员函数,成员类或不需要实例化的类模板的静态数据成员.

现在,当然不需要有一个函数定义来获取它的地址.我们可以获取前向声明函数的地址,并将它们定义在不同的转换单元中.

既然如此,我不知道什么时候需要它.然而,编译器似乎有自己的想法.在GCC和VC上进行测试,这里有几个例子:

template <typename T> void CallBanana() { T::Banana(); }
template <typename T> void CallUnimpl();

template <typename T>
struct S {
    static void CallBanana() { T::Banana(); }
    static void CallOrange() { T::Orange(); }
    static void CallUnimpl();
};

struct B { static void Banana() {} };

int main() {
    (void)(&CallBanana<void>); // 1
    (void)(&CallUnimpl<void>); // 2
    (void)(&S<void>::CallBanana); // 3
    (void)(&S<void>::CallOrange); // 4
    (void)(&S<void>::CallUnimpl); // 5
    (void)(&S<B>::CallBanana); // 6
}
Run Code Online (Sandbox Code Playgroud)

这些应该一次评论一次以查看效果.

在这里测试的 GCC 4.7 将抱怨1,3和4.因此它实例化所有定义(如果它们存在).

VC 2010(没有在线测试,抱歉)实例化3和4,但没有实例化1.

此处测试的 …

c++ templates language-lawyer

7
推荐指数
1
解决办法
619
查看次数