clang 5:std ::可选的实例化螺钉std :: is_constructible参数类型的特征 [英] clang 5: std::optional instantiation screws std::is_constructible trait of the parameter type
问题描述
切换到c ++ 17并将标准的自定义 std :: optional
解决方案替换为c ++ 17时,检测到了clang 5的一种非常奇怪的意外行为。由于某些原因, emplace()
由于对参数的 std :: is_constructible
性状的错误评估而被禁用
A really strange and unexpected behaviour of clang 5 was detected when switching to c++17 and replacing custom std::optional
solution with the standard one. For some reason, emplace()
was being disabled due to faulty evaluation of a std::is_constructible
trait of the parameter class.
在复制之前必须满足一些特定的先决条件:
Some specific preconditions must be satisfied before it reproduces:
#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);
}
};
更改任何前提条件,并按预期进行编译。标准中是否存在一些未知的不一致之处,使得clang在遵守标准时会拒绝此代码?
Change any of the preconditions and it compiles as expected. Is there some unknown inconsistency in the standard that makes clang reject this code while being compliant?
作为补充说明: GCC 7.1 和 GCC 7.2 上面的代码没有问题。
As a side note: GCC 7.1 and GCC 7.2 have no problem with the above code.
错误报告位于: bugs.llvm.org
推荐答案
这看起来像是编译器错误。来自 [class]
This looks like a compiler bug. From [class]
在类说明符的结尾
}
中,类被认为是完全定义的对象类型(或完整类型)。 / p>
A class is considered a completely-defined object type (or complete type) at the closing
}
of the class-specifier.
这意味着受害者
在 std处完成::可选的< Victim>
,使其在这种情况下与其他任何类型都没有区别。
Which means Victim
is complete at std::optional<Victim>
, making it no different than any other type in this context.
来自 [元]
当且仅当以下变量定义在某些情况下格式正确时,才能满足模板专门化
is_constructible< T,Args ...>
的谓词条件。发明的变量t
:
T t(declval< Args>()...);
The predicate condition for a template specialization
is_constructible<T, Args...>
shall be satisfied if and only if the following variable definition would be well-formed for some invented variablet
:T t(declval<Args>()...);
哪个正在直接初始化 t
并使用类型的参数Args ...
,或者如果 sizeof ...(Args)== 0
,则它是值初始化 t
。
Which is direct-initializing t
with arguments of type Args...
, or if sizeof...(Args) == 0
, it's value-initializing t
.
在这种情况下,值初始化 t
是默认初始化 t
,因此 std :: is_constructible_v< Victim>
应该是正确的。
In this case, value-initializing t
is to default-initialize t
, which is valid hence std::is_constructible_v<Victim>
should be true.
话虽如此,编译器似乎是尽力很多 进行编译。
With all that said, compilers seems to be struggling a lot compiling this.
这篇关于clang 5:std ::可选的实例化螺钉std :: is_constructible参数类型的特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!