显式实例化失败的原因是什么?

时间:2018-01-14 01:17:12

标签: c++ templates metaprogramming generic-programming

/* MyClass.h */
class MyClass
{
public:
    template <typename T>
    void Foo(const T &val);
};

/* MyClass.cpp */
#include <string>
#include <iostream>

#define EXPLICIT_INSTANTIATION_FOO(MyType) \
    template void MyClass::Foo(const MyType &val)

EXPLICIT_INSTANTIATION_FOO(int);
EXPLICIT_INSTANTIATION_FOO(float);
EXPLICIT_INSTANTIATION_FOO(std::string);

template <typename T>
void MyClass::Foo(const T &val)
{
    std::cout << "My Value: " << val << std::endl;
}

由于某些其他原因,我无法在头文件中定义Foo,然后我尝试显式实例化源文件中所需的所有类型。它在g ++ - 4.8上运行得很好。

然后,一旦我提交了代码,我发现Windows 10, x86_64, cl19上的建筑失败了。这是一个未解决的符号错误,看起来我的实例化没有从对象中暴露出来。

但有趣的是,当我尝试通过上面的简单片段在我自己的Windows上重现此错误时。我发现它在我的vs2017上使用cl19 ...

公司和个人计算机之间会有数以千计的配置不同,但我只是不知道实例化在那里工作的原因是什么......任何想法都赞赏! :)

补充剂:

仅供参考,完整的代码在这里:

/* MyClass.h */
#pragma once
class MyClass
{
public:
    MyClass();
    ~MyClass();

    template <typename T>
    void Foo(const T &val);
};

/* MyClass.cpp */
#include "MyClass.h"
#include <iostream>
#include <string>

#define EXPLICIT_INSTANTIATION_FOO(MyType) \
    template void MyClass::Foo(const MyType &val)

EXPLICIT_INSTANTIATION_FOO(int);
EXPLICIT_INSTANTIATION_FOO(float);
EXPLICIT_INSTANTIATION_FOO(std::string);

MyClass::MyClass() {}

MyClass::~MyClass() {}

template <typename T>
void MyClass::Foo(const T &val)
{
    std::cout << "My Value: " << val << std::endl;
}

/* main.cpp */
#include "MyClass.h"
#include <iostream>
#include <string>

int main()
{
    std::string v = "hello";
    MyClass cls;

    cls.Foo(v);

    std::cin.get();
    return 0;
}

通过了msvc上的编译。

2 个答案:

答案 0 :(得分:1)

将函数定义移至EXPLICIT_INSTANTIATION_FOO调用之前。这是一个永远不应该工作的东西,但是编译器,它们正慢慢地在它上面。如果你想让msvc拒绝它,请使用/ permissive-标志。

答案 1 :(得分:0)

谢谢大家,这个愚蠢的问题已经解决了。

原因是模板实例化不会从Windows上的模板定义继承dllexport属性。显然,它适用于我愚蠢的测试代码,因为它没有被编译为DLL :))