代码之家  ›  专栏  ›  技术社区  ›  yuri kilochek

声明具有C语言链接类型的函数模板合法吗?

  •  2
  • yuri kilochek  · 技术社区  · 6 月前

    :

    extern "C" {
        template<typename T>   // error: template with C linkage
        void bad_f() {}
    }
    

    然而,GCC和Clang都接受非模板C的函数模板

    extern "C" {
        using F = void();
    }
    
    template<typename T>
    F f;
    
    template<typename T>
    void f() {}
    

    f 语言联系 (即发生名称篡改)并用C键入 语言联系 (即使用C调用约定来调用它们)。

    f 声明实际上是格式良好的C++?如果是这样,它是否像我假设的那样?

    1 回复  |  直到 6 月前
        1
  •  4
  •   Davis Herring    6 月前

    CWG1463 。由于以下几个原因,所讨论的限制没有多大意义:

    1. 语言连接被描述为 extern "C" 是名字的扭曲)和 函数类型 (这是调用约定),函数模板不是这些东西(尽管有[temp.pre]/6)
    2. 我们不可能希望为函数模板的每个专门化(无论如何,它都不是一个名称有外部链接的函数)提供C语言链接,因为(如上所述)只有一个未标记的名称
    3. 别名模板可以从其定义中的函数类型的“具有”C语言链接中受益,并且对其没有任何其他潜在意义

    您的声明 f 这几乎就是最后一点的一个例子:使用模板来制造C兼容的函数(C中的函数指针使用)非常有用,但用类型别名声明一个函数的技巧仅在函数类型不是C的特殊情况下有效 依赖的 .

    因此,我们(终于)写了一篇 paper (链接于12月上线)已被批准(但尚未应用)为缺陷报告:它完全删除了有问题的规则,让模板声明中的函数类型具有C语言链接,并正式禁止

    template<class> extern "C++" void f();
    

    (这些实现一直被拒绝)以便我们有一天可以指定该语法覆盖由封闭的函数类型语言链接所隐含的函数类型-语言链接, extern "Java" 如果这种情况变得普遍的话。