自 Visual Studio 17.2 起使用 __declspec(dllexport) 时出现未定义的类

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

以下代码对于 Visual Studio 编译良好< 17.2:

#include <optional>
#include <map>

class __declspec(dllexport) A {
    using M = std::map<int, A>;
    std::optional<M> map_;
};

但是对于 Visual Studio 17.2 及更高版本,失败,并出现错误:

example.cpp
...utility(330): error C2079: 'std::pair<const int,A>::second' uses undefined class 'A'
...optional(159): note: see reference to class template instantiation 'std::pair<const int,A>' being compiled
...optional(158): note: while compiling class template member function 'void std::_Optional_construct_base<_Ty>::_Construct_from<const _Base&>(_Self) noexcept(<expr>)'
        with
        [
            _Ty=A::M,
            _Base=std::_Optional_construct_base<A::M>,
            _Self=const std::_Optional_construct_base<A::M> &
        ]
Compiler returned: 2

如果我从代码中删除

__declspec(dllexport)
或将
std::optional
更改为
boost::optional
,它在任何版本中都可以正常工作。

这是编译器错误,还是我遗漏了什么?

c++ visual-studio dllexport stdoptional
1个回答
0
投票

stl 中的“错误”不是现在出现的,而是在以前的版本中出现的。看,问题是 std 可选要求类型为

is_trivially_destructible
https://en.cppreference.com/w/cpp/types/is_destructible

从c++20版本开始,

std::optional
变成了
constexpr
。因此,析构函数不是在运行时实现的,而是在编译时实现的。看 https://en.cppreference.com/w/cpp/utility/optional/~可选

回到您的代码示例,您的类

A
不是
is_trivially_destructible
,因为它包含
map_
M
,它可以包含相同的类
A
作为对象,而不是作为引用 - 因此,它是一个复杂的对象。 为什么
__declspec(dllexport)
会影响:在
std::optional
变成
constexpr
之前,
std::optional
的析构函数已经由您的编译器在 DLL 中生成。现在它应该在编译时由将使用您的 DLL 的编译器生成,但它实际上无法生成它,因为类 A 是它的外部并且显然不是
is_trivially_destructible
因此,编译器的行为是合理的,尽管并不明显。要更详细地了解问题,请尝试执行以下代码:

#include <optional> #include <string> #include <map> class __declspec(dllexport) A { public: mutable std::optional<A> a_; };

你会看到问题
is_trivially_destructible

:

error C2139: 'A': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_trivially_destructible'

我不认为 
boost::optional

可以成为解决方案,因为也许在

constexpr
的下一个版本中它也会出现。正确的改变是简化代码逻辑并通过指针或引用存储类,在这种情况下,
std::optional
的类型将变得微不足道。
    

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