链接到ar后,专用成员函数丢失

Ale*_*mer 3 c++ linker templates unix-ar

考虑以下最小的示例,它在一个更大的项目中重现问题:

spec.h:

#include <iostream>

class A
{
public:
    template<typename T>
    T test(const std::string& a)
    {
        std::cout << "DEFAULT CALLED WITH " << a << "\n";
        return T();
    }
};
Run Code Online (Sandbox Code Playgroud)

other.cpp:

#include "spec.h"

template<>
float A::test<float>(const std::string& a)
{
    std::cout << "SPECIAL CALLED WITH " << a << "\n";
    return float();
}
Run Code Online (Sandbox Code Playgroud)

spec.cpp:

#include <iostream>
#include "spec.h"

int main()
{
    A a;
    a.test<int>("int");
    a.test<float>("float");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

汇编:

$ make
rm -f *.o lib.a output
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
ar cr lib.a other.o
clang++ -g -o output lib.a spec.o
rm -f *.o output2
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
clang++ -g -o output2 other.o spec.o

$ ./output
DEFAULT CALLED WITH int
DEFAULT CALLED WITH float

$ ./output2
DEFAULT CALLED WITH int
SPECIAL CALLED WITH float
Run Code Online (Sandbox Code Playgroud)

题:

为什么会这样?是不是以某种方式被剥夺了?lib.a和直接对象文件的使用有什么区别?:-)

谢谢!

Ben*_*igt 8

从第14.7.3p6节:

如果模板,成员模板或类模板的成员是显式专用的,则应在首次使用该特化之前声明该特化,这将导致发生隐式实例化,在发生此类使用的每个翻译单元中 ; 无需诊断.如果程序没有为显式特化提供定义,并且特殊化的使用方式会导致隐式实例化或成员是虚拟成员函数,则程序格式错误,无需诊断.

您的程序格式不正确,因为您在spec.cpp中使用了特殊化而没有在该翻译单元中首先声明它.或者,如下段所述:

为函数模板,类模板,类模板的成员函数,类模板的静态数据成员,类模板的成员类,类模板的成员枚举,类模板的成员类模板,类的成员函数模板放置显式特化声明模板,类模板成员模板的成员函数,非模板类成员模板的成员函数,类模板成员类的成员函数模板等,以及类模板的部分特化声明的放置,成员类模板非模板类,类模板的成员类模板等可以根据显式专业化声明的相对位置及其在翻译单元中的实例化点(如上下文所述)来影响程序是否格式良好.

写专业时
要注意它的位置;
或者使它编纂
将是一种
试图点燃其自焚的试验.

我投票选为整个标准中最棒的段落利默里克.

  • 在spec.h的底部添加一个前向声明`template <> float A :: test <float>(const std :: string&a);` (2认同)