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

问题描述 投票:0回答:1

编辑此问题已被大量修改

我试图从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导入/导出的特点,它是什么?

c++ visual-c++ dll
1个回答
1
投票

语言规范说

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.