(编辑)如何在Windows中导出模板专业化,并在cpp文件中声明源

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(编辑)如何在Windows中导出模板专业化,并在cpp文件中声明源相关的知识,希望对你有一定的参考价值。

编辑此问题已被大量修改

我试图从cpp文件中定义的dll导出模板特化(纯粹是为了导出模板)。

基于在头文件中使用dllimport / export的第一次尝试(“First Attempt”)结果在编译和运行时都有效,但它产生了C4661警告(没有为显式模板实例化请求提供合适的定义)。这是我第一次提出这个问题。然而@AnT答案显示我的错误,我试图通过“第二次尝试”来纠正这一点,但这也会导致警告。

第一次尝试

foo.h中

#ifndef _foo_h_ //header guard
#define _foo_h_

#ifdef EXAMPLE_FOO_EXPORTS
#define EXAMPLE_FOO_EXPORT __declspec(dllexport)
#define EXAMPLE_FOO_EXTERN
#else
#define EXAMPLE_FOO_EXPORT __declspec(dllimport)
#define EXAMPLE_FOO_EXTERN extern
#endif

template<typename _Type>
class foo
{
public:
    _Type value();
};

EXAMPLE_FOO_EXTERN template class EXAMPLE_FOO_EXPORT foo<int>;

#endif//_foo_h_

Foo.cpp中

#include "foo.h"

template<typename _Type> 
_Type foo<_Type>::value()
{
    return (_Type)1;
}

我在dll中有一段测试代码输出一个值。

TEST.CPP

#include "foo.h"

int readValue()
{
    foo<int> test;

    return test.value();
}

第二次尝试

关于@ AnT关于标准的说明,在cpp中实例化工作,但我留下了另一个问题(授予这是所有VC-fu)。将代码更改为以下以确保实例化在cpp中完成(按标准并使dll导出工作),我得到一个警告C4251:'bar :: value':类'foo'需要有dll-interface才能结构'bar'的客户使用。

foo.h中

#ifndef _foo_h_ //header guard
#define _foo_h_

#ifdef EXAMPLE_FOO_EXPORTS
#define EXAMPLE_FOO_EXPORT __declspec(dllexport)
#define EXAMPLE_FOO_EXTERN
#else
#define EXAMPLE_FOO_EXPORT __declspec(dllimport)
#define EXAMPLE_FOO_EXTERN extern
#endif

template<typename _Type>
class foo
{
public:
    _Type value();
};

typedef foo<int> fooInt;

#ifndef EXAMPLE_FOO_EXPORTS
extern template class __declspec(dllimport) foo<int>;
#endif

struct EXAMPLE_FOO_EXPORT bar
{
    fooInt value;
};
#endif//_foo_h_

Foo.cpp中

#include "foo.h"

template<typename _Type> 
_Type foo<_Type>::value()
{
    return (_Type)1;
}

#ifdef EXAMPLE_FOO_EXPORTS
template class __declspec(dllexport) foo<int>;
#endif

我相信bar结构在使用__declspec(dllexport)在cpp中实例化之前实例化foo模板。除了“这是疯了,这都是错的,为什么你这样做”,有没有办法绕过这个或者这只是windows dll导入/导出的特点,它是什么?

答案

语言规范说

14.7.2显式实例化 9定义类模板特化的显式实例化定义显式实例化类模板特化,并且是仅在实例化时定义的那些成员的显式实例化定义。

在您的情况下,您的显式实例化定义不会为foo<int>::value()提供显式实例化定义,因为在显式实例化时,该成员尚未定义。

C4661的目的是告知您该问题。 MSVC很有可能对dllexport-ed实体应用特殊处理,这最终使您的代码能够正确链接。但从语言的角度来看问题是存在的。

以上是关于(编辑)如何在Windows中导出模板专业化,并在cpp文件中声明源的主要内容,如果未能解决你的问题,请参考以下文章

如何从浏览器 SSL/TLS 会话中导出主密钥?

如何在行和列中排列对象并在.svg中导出[关闭]

动态链接库中导出模板函数

从一个 GET 请求中导出输入查询并在单独的请求中使用它们

从数据库中导出 XML 文件并在实际列之前获得没有任何属性的干净格式

有啥方法可以在 ROR 中导出(生成)可编辑的 PDF?