Different results in Clang and GCC when casting to std::optional<T>

风格不统一 提交于 2019-12-03 09:50:57

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!