以下代码编译并链接Visual Studio
(2017 年和 2019 年/permissive-
),但不与任何一个编译gcc
or clang
.
foo.h
#include <memory>
struct Base {
virtual ~Base() = default; // (1)
};
struct Foo : public Base {
Foo(); // (2)
struct Bar;
std::unique_ptr<Bar> bar_;
};
foo.cpp
#include "foo.h"
struct Foo::Bar {}; // (3)
Foo::Foo() = default;
main.cpp
#include "foo.h"
int main() {
auto foo = std::make_unique<Foo>();
}
我的理解是,在main.cpp
, Foo::Bar
必须是完整类型,因为尝试删除它~Foo()
,它是隐式声明的,因此在访问它的每个翻译单元中隐式定义。
然而,Visual Studio
不同意,并接受此代码。此外,我发现以下更改使Visual Studio
拒绝代码:
- Making
(1)
非虚拟的
- 定义
(2)
内联——即Foo() = default;
or Foo(){};
- 去除
(3)
在我看来好像Visual Studio
在以下条件下使用的任何地方都不会定义隐式析构函数:
- 隐式析构函数是虚拟的
- 该类有一个在不同翻译单元中定义的构造函数
相反,它似乎只在翻译单元中定义析构函数,该翻译单元还包含第二个条件中构造函数的定义。
所以现在我想知道:
- 这是允许的吗?
- 是否在任何地方指定或至少已知
Visual Studio
做这个?
Update:我已提交错误报告https://developercommunity.visualstudio.com/content/problem/790224/implictly-declared-virtual-destructor-does-not-app.html。让我们看看专家对此有何看法。
我相信这是 MSVC 中的一个错误。至于std::default_delete::operator()
,标准说[unique.ptr.dltr.dflt/4]:
Remarks:如果 T 是不完全类型,则程序格式不正确.
既然没有“无需诊断”子句,一个符合标准的 C++ 编译器需要发出诊断书 [简介.合规性/2.2]:
如果一个程序包含违反任何可诊断的规则或者...,一个符合要求的实现应发出至少一条诊断消息.
和...一起[简介/合规性/1]:
的集合可诊断的规则包含本文档中的所有语法和语义规则,但包含“不需要诊断”的明确表示法或被描述为导致“未定义行为”的规则除外。
海湾合作委员会使用static_assert
诊断类型完整性。 MSVC 似乎不执行这样的检查。如果它默默地传递一个参数std::default_delete::operator()
to delete
,那么,这会导致未定义的行为。这可能与你的观察相符。它可能有效,但在文档保证它(作为非标准 C++ 扩展)之前,我不会使用它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)