c++ - 使用 C 调用约定调用函数模板特化

标签 c++ templates

我有以下模板

template<typename T> void f(T t) { }

我想将它的特定特化的地址传递给 C 函数

g(&f<int>);

但是因为我想要可移植性,我希望“f”的调用约定与 C 的调用约定匹配。所以我试验了语言链接如何影响调用约定并发现

  • 函数类型的语言链接影响使用的调用约定
  • 函数名的语言链接会影响修饰

C++ 规范的语言链接部分说

In a linkage-specification, the specified language linkage applies to the function types of all function declarators, function names with external linkage, and variable names with external linkage declared within the linkage-specification.

因此,为了防止模板在目标文件中区分不同的特化需要禁用 mangling,我按如下进行

extern "C" {
    /* function name will not be affected */
    template<typename T> static void f(T t) { }
}

但是它给了我一个编译器错误,说模板不能有 C 语言链接,我认为这意味着它提示函数模板的函数类型。事实上,我发现规范说明

A template, a template explicit specialization (14.7.3), and a class template partial specialization shall not have C linkage

现在对我来说很明显我们不想更改 name 的链接,因为我们依赖于 mangling 来工作。但是禁止更改type 的链接的原因是什么?它似乎限制我们必须使用 C++ 调用约定;有人知道原因吗?是否有一个简单的解决方法来实现我最初的目标?


我改变了我现在尝试只给类型链接的方式,如下

extern "C" typedef void ftype(int);

template<typename T>
ftype f;

这很好用。遗憾的是,在使用这种技术时,我没有看到定义 f 的方法。但无论如何,我试过的编译器都没有诊断出这个(试过 EDG/comeau、GCC 和 clang),尽管这看起来和以前的情况完全一样:名称应该没有 C 语言链接,但只有类型有。

谁能解释一下?

最佳答案

C 头文件是什么样的?在某处,C 源代码必须枚举允许的回调类型。您应该借此机会拥有一系列宏,这些宏可为各个 stub 函数生成原型(prototype),并在 C++ 源代码中生成相应的宏序列 extern "C" stub 。


关于第二个问题:是的,这行得通,但是 typedef不在模板内。我试图将这样的 typedef 放入类中,但事实证明,extern "C" 中甚至不允许使用类模板。 .所以你可以有一个函数模板,但没有依赖类型的参数。

仅仅定义那个函数很简单:

extern "C" typedef void ftype(int);

template<typename T>
static ftype f; // <- added "static" here

template< typename T >
void f(int q) {}

啊哈,可变函数!

extern "C" typedef void ftype( int, ... );

template<typename T>
static ftype f;

template< typename T >
static void f( int z, ... ) {
    va_list va;
    va_start( va, z );
    T v = va_arg( va, T );
    va_end( va );

    std::cout << v;
}

你真的不需要类型推导,因为它只是一个回调,所以你可以传递这个 & f<int>到 C 代码,所有回调都具有相同的类型,它可以在运行时确定类型并通过可变参数传递它想要的任何东西。

关于c++ - 使用 C 调用约定调用函数模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49169080/

相关文章:

c++ - 主类中有多个派生类的重新定义错误

c++ - QGridLayout : change height of a row

c++ - std::function 可以是类数据成员吗?

javascript - 获取动态创建的验证容器以随元素滚动

c++ - 迭代器相等

c++ - 如何发送C++和mysql动态mysql查询

c++ - 如何在 C++ 中使用模板制作通用 map

visual-studio - MVC 4 Web API 模板 - 可以删除的内容

C++模板自定义警告

javascript - pure.js 必须与现有页面节点一起使用吗?