clang 5:std ::可选的实例化螺钉std :: is_constructible参数类型的特征 [英] clang 5: std::optional instantiation screws std::is_constructible trait of the parameter type

查看:133
本文介绍了clang 5:std ::可选的实例化螺钉std :: is_constructible参数类型的特征的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

切换到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);
    }
};






godbolt.org

更改任何前提条件,并按预期进行编译。标准中是否存在一些未知的不一致之处,使得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 variable t: 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆