在转换为std :: optional时,Clang和GCC中的不同结果<optional>&lt; T&gt; [英] Different results in Clang and GCC when casting to std::optional&lt;T&gt;

查看:188
本文介绍了在转换为std :: optional时,Clang和GCC中的不同结果<optional>&lt; T&gt;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下代码:

  #include > 
#include< optional>

struct foo
{
显式运算符std ::可选< int>(){
返回std ::可选< int>(1);
}
显式运算符int(){
return 0;
}
};

int main()
{
foo my_foo;
std ::可选< int> my_opt(my_foo);
std :: cout<< value:<< my_opt.value()<<的std :: ENDL;
}

gcc 7.2.0写道 值:1



MSVC 2017 (15.3)和 clang 4.0.0然而写 value:0

根据C ++标准哪一个是正确的?

解决方案

既然这是直接初始化,我们列举构造函数并选择最好的一个。 std :: optional 的相关构造函数

  constexpr可选(const optional& other); //(2)
constexpr可选(可选&& other)noexcept(/ *见下文* /); //(3)

模板< class U = value_type>
/ * EXPLICIT * / constexpr可选(U&& value); //(8),其中U = foo&

两者都可行((8))如果 int 可以从 foo& foo 既不是 std :: in_place_t 也不是 std :: optional< int> ,所有这些都成立) (8)是完全匹配,而(2)(3)需要用户定义的转换,所以它应该是首选。 gcc在这里是错误的。 然而,gcc实际上并没有调用(3)。它只是从将 my_foo 转换为可选< int>的结果中直接初始化 my_opt / code>。这个使用gcc 7.2的程序打印 3 但没有 1a 1b 2

  #include< iostream> 

模板< class T>
struct opt {
opt(){}
opt(opt const&){std :: cout<< 1a\\\
; }
opt(opt&& amp;){std :: cout<< 1b\\\
; }

模板< class U>
opt(U& amp; amp; amp; amp; amp; amp; amp; amp; ampc){std :: cout<< 2\\\
; }
};

struct foo
{
显式运算符opt< int>(){std :: cout<< 3\\\
;返回{}; }
};

int main()
{
opt< int> O(FOO {});
}

我不认为这是允许的路线。我提交了 81952


Given the following code:

#include <iostream>
#include <optional>

struct foo
{
    explicit operator std::optional<int>() {
        return std::optional<int>( 1 );
    }
    explicit operator int() {
        return 0;
    }
};

int main()
{
    foo my_foo;
    std::optional<int> my_opt( my_foo );
    std::cout << "value: " << my_opt.value() << std::endl;
}

gcc 7.2.0 writes value: 1.

MSVC 2017 (15.3) and clang 4.0.0 however write value: 0.

Which one is correct according to the C++ standard?

解决方案

Since this is direct-initialization, we enumerate the constructors and just pick the best one. The relevant constructors for std::optional are :

constexpr optional( const optional& other ); // (2)
constexpr optional( optional&& other ) noexcept(/* see below */); // (3)

template < class U = value_type >
/* EXPLICIT */ constexpr optional( U&& value ); // (8), with U = foo&

Both are viable ((8) only participates in overload resolution if int is constructible from foo& and foo is neither std::in_place_t nor std::optional<int>, all of which hold), but (8) is an exact match whereas (2) and (3) require a user-defined conversion, so it should be preferred. gcc is wrong here.

However, gcc doesn't actually invoke (3) either. It just directly initializes my_opt from the result of converting my_foo to an optional<int>. This program with gcc 7.2 prints 3 but none of 1a, 1b, or 2:

#include <iostream>

template <class T>
struct opt {
    opt() { }
    opt(opt const& ) { std::cout << "1a\n"; }
    opt(opt&& ) { std::cout << "1b\n"; }

    template <class U>
    opt(U&& ) { std::cout << "2\n"; }
};

struct foo 
{
    explicit operator opt<int>() { std::cout << "3\n"; return {}; }
};

int main()
{
    opt<int> o(foo{});
}

I don't think that's an allowable route. I filed 81952.

这篇关于在转换为std :: optional时,Clang和GCC中的不同结果<optional>&lt; T&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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