带有LLVM-Clang的私有C ++模板的隐式实例化的链接器错误 [英] Linker error with implicit instantiation of private C++ template with LLVM-Clang

查看:91
本文介绍了带有LLVM-Clang的私有C ++模板的隐式实例化的链接器错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

免责声明:我知道模板通常是在头文件中实现的.请通读.

我有一个与C ++模板有关的问题.我的代码在Windows下使用MSVC构建,但在Mac OSX下不使用LLVM-Clang构建,但是我不确定哪一个是错误的.

I have a C++ template-related issue. My code builds with MSVC under Windows but doesn't with LLVM-Clang under Mac OSX, but I'm not sure which one is wrong.

这是一个简单的测试用例,由三个源文件组成:

Here is a simple test case, composed of three source files:

  • main.cpp

  • main.cpp

#include "templ.h"

int main()
{
   templ(1);
   return 0;
}

  • templ.h

  • templ.h

    template<typename T>
    T templ(const T&);
    

  • templ.cpp

  • templ.cpp

    #include "templ.h"
    
    template<typename T>
    T templ(const T& t)
    {
       return t;
    }
    
    //explicit instantiation
    template int templ(const int&);
    
    //implicit instantiation
    void f()
    {
       templ(1);
    }
    

  • 如您所见,我希望功能模板的实现是私有的(即隐藏在.cpp文件中).为此,我必须在与模板定义相同的翻译单元中实例化我的模板.在上面的示例中,我仅实例化templ<int>. AFAIK,这是不寻常的,但C ++非常复杂.

    As you can see, I want the implementation of the function template to be private (i.e. hidden in the .cpp file). To allow this, I must instantiate my template in the same translation unit as its definition. In the above example, I only instantiate templ<int>. AFAIK, this is unusual, but perfectly cromulent C++.

    按原样,此代码使用两个编译器进行构建.但是,如果我注释掉显式实例化而仅保留隐式实例化,则编译器的行为将有所不同. MSVC构建成功,但是LLVM-Clang失败,并出现以下链接器错误:

    As is, this code builds with both the compilers. However, if I comment out the explicit instantiation and only leave the implicit instantiation, the compilers behave differently. MSVC builds successfuly, but LLVM-Clang fails with the following linker error:

    Undefined symbols for architecture x86_64:
      "int templ<int>(int const&)", referenced from:
          _main in main.cpp.o
    ld: symbol(s) not found for architecture x86_64
    

    此外,该错误仅在启用优化后才会发生(例如-02).

    Besides, that error occurs only when the optimization is enabled (e.g. -02).

    标准对此有何表述?这是LLVM-Clang的已知行为/错误吗?

    What does the standard say about this? Is this a known behavior/bug of LLVM-Clang?

    我的LLVM-Clang版本是:

    My version of LLVM-Clang is:

    Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
    Target: x86_64-apple-darwin13.0.0
    Thread model: posix
    

    很抱歉,如果这是重复的.选择正确的关键字非常困难.

    Sorry if this is a duplicate. It's very hard to pick the correct keywords.

    推荐答案

    这是正常现象,是预期的结果.

    This is normal and expected.

    14个模板
    6除非隐式实例化了每个翻译单元(14.7.1),否则应在每个转换单元中定义函数模板,类模板的成员函数,变量模板或类模板的静态数据成员,除非显式实例化了相应的专业化(14.7). .2)在某些翻译单位中;无需诊断.

    14 Templates
    6 A function template, member function of a class template, variable template, or static data member of a class template shall be defined in every translation unit in which it is implicitly instantiated (14.7.1) unless the corresponding specialization is explicitly instantiated (14.7.2) in some translation unit; no diagnostic is required.

    根据您的情况,这意味着当删除templ的显式实例时,编译器可以选择

    As applied to your case, this means that when the explicit instantiation of templ is removed, the compiler can either

    1. 通常由于同一TU中的隐式实例化而生成实例化;或
    2. 内联对templ的调用,并且不生成任何外部可用的实体.
    1. generate an instantiation normally because of the implicit instantiation in the same TU; or
    2. inline the call to templ and not generate any externally usable entity.

    对于符合标准的实现,均允许使用任何一种行为.如果您确定某处有显式实例化,则两者都会产生有效的目标代码.如果不这样做,您可能会或可能不会收到错误,这是您自己的错.

    Either behaviour is permitted for a conforming implementation. If you make sure there's an explicit instantiation somewhere, either will produce valid object code. If you don't, you may or may not get an error and it's your own fault.

    这篇关于带有LLVM-Clang的私有C ++模板的隐式实例化的链接器错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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