зеркало из https://github.com/microsoft/STL.git
Short-circuit some `variant` constraints (#4966)
This commit is contained in:
Родитель
1e312b38db
Коммит
f8f9f7aff1
|
@ -934,12 +934,13 @@ public:
|
|||
: _Mybase(in_place_index<0>) {} // value-initialize alternative 0
|
||||
|
||||
template <class _Ty,
|
||||
enable_if_t<sizeof...(_Types) != 0 //
|
||||
&& !is_same_v<_Remove_cvref_t<_Ty>, variant> //
|
||||
&& !_Is_specialization_v<_Remove_cvref_t<_Ty>, in_place_type_t> //
|
||||
&& !_Is_in_place_index_specialization<_Remove_cvref_t<_Ty>> //
|
||||
&& is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>, //
|
||||
int> = 0>
|
||||
enable_if_t<sizeof...(_Types) != 0 && !is_same_v<_Remove_cvref_t<_Ty>, variant>
|
||||
&& !_Is_specialization_v<_Remove_cvref_t<_Ty>, in_place_type_t>
|
||||
&& !_Is_in_place_index_specialization<_Remove_cvref_t<_Ty>>,
|
||||
int> = 0,
|
||||
// These enable_if_t constraints are distinct to enable short-circuiting and avoid
|
||||
// substitution into _Variant_init_type when the first constraint is not satisfied.
|
||||
enable_if_t<is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>, int> = 0>
|
||||
constexpr variant(_Ty&& _Obj) noexcept(is_nothrow_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>)
|
||||
: _Mybase(in_place_index<_Variant_init_index<_Ty, _Types...>::value>, static_cast<_Ty&&>(_Obj)) {
|
||||
// initialize to the type selected by passing _Obj to the overload set f(Types)...
|
||||
|
@ -976,8 +977,10 @@ public:
|
|||
// initialize alternative _Idx from _Ilist and _Args...
|
||||
}
|
||||
|
||||
template <class _Ty, enable_if_t<!is_same_v<_Remove_cvref_t<_Ty>, variant>
|
||||
&& is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>
|
||||
template <class _Ty, enable_if_t<!is_same_v<_Remove_cvref_t<_Ty>, variant>, int> = 0,
|
||||
// These enable_if_t constraints are distinct to enable short-circuiting and avoid
|
||||
// substitution into _Variant_init_type when the first constraint is not satisfied.
|
||||
enable_if_t<is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>
|
||||
&& is_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>,
|
||||
int> = 0>
|
||||
_CONSTEXPR20 variant& operator=(_Ty&& _Obj)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <functional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
@ -909,6 +910,33 @@ namespace msvc {
|
|||
}
|
||||
}
|
||||
} // namespace assign_cv
|
||||
|
||||
namespace gh4959 {
|
||||
// Test GH-4959 "P0608R3 breaks flang build with Clang"
|
||||
// Constraints on variant's converting constructor and assignment operator templates reject arguments of the
|
||||
// variant's type, but did not short-circuit to avoid evaluating the constructibility constraint. For this
|
||||
// program, the constructibility constraint is ill-formed outside the immediate context when determining if
|
||||
// variant<optional<GenericSpec>> can be initialized from an rvalue of the same type.
|
||||
|
||||
template <typename... RvRef>
|
||||
using NoLvalue = std::enable_if_t<(... && !std::is_lvalue_reference_v<RvRef>)>;
|
||||
|
||||
struct Name {};
|
||||
|
||||
struct GenericSpec {
|
||||
template <typename A, typename = NoLvalue<A>>
|
||||
GenericSpec(A&& x) : u(std::move(x)) {}
|
||||
GenericSpec(GenericSpec&&) = default;
|
||||
std::variant<Name> u;
|
||||
};
|
||||
|
||||
struct InterfaceStmt {
|
||||
template <typename A, typename = NoLvalue<A>>
|
||||
InterfaceStmt(A&& x) : u(std::move(x)) {}
|
||||
InterfaceStmt(InterfaceStmt&&) = default;
|
||||
std::variant<std::optional<GenericSpec>> u;
|
||||
};
|
||||
} // namespace gh4959
|
||||
} // namespace msvc
|
||||
|
||||
int main() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче