【发布时间】:2018-06-07 01:53:08
【问题描述】:
当切换到 c++17 并用标准解决方案替换自定义 std::optional 解决方案时,检测到 clang 5 的一个非常奇怪和意外的行为。出于某种原因,由于对参数类的 std::is_constructible 特征的错误评估,emplace() 被禁用。
在复制之前必须满足一些特定的先决条件:
#include <optional>
/// Precondition #1: T must be a nested struct
struct Foo
{
struct Victim
{
/// Precondition #2: T must have an aggregate-initializer
/// for one of its members
std::size_t value{0};
};
/// Precondition #3: std::optional<T> must be instantiated in this scope
std::optional<Victim> victim;
bool foo()
{
std::optional<Victim> foo;
// An error
foo.emplace();
/// Assertion is failed
static_assert(std::is_constructible<Victim>::value);
}
};
godbolt.org 上的实时示例
更改任何先决条件并按预期编译。标准中是否存在一些未知的不一致,导致 clang 在合规的同时拒绝此代码?
附带说明:GCC 7.1 和 GCC 7.2 对上述代码没有任何问题。
错误报告地址:bugs.llvm.org
【问题讨论】:
-
很可能是编译器错误。
-
@CrisLuengo,我希望如此,因为它比标准更容易修复。
-
实际上,您的问题是语言律师问题。应该这样回答。
-
检查this。这是所涉及特征的简单实现,在这种情况下应该都是正确的。 gcc 7.2 有最详细的错误消息 “在解析 'Foo::Victim::value' 的非静态数据成员之前需要构造函数”
-
似乎任何默认初始化程序与可选成员都嵌套在结构中的组合打破了这一点。 ` = 0` 而不是
value上的 {0} 也会失败。
标签: c++ language-lawyer c++17 stdoptional