+2016-11-14 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Implement P0504R0 (Revisiting in-place tag types for
+ any/optional/variant).
+ * include/std/any (any(_ValueType&& __value)): Constrain
+ the __is_in_place_type with the decayed type.
+ (make_any): Adjust to use the new tag type.
+ * include/std/utility (in_place_tag): Remove.
+ (in_place_t): Turn into a non-reference tag type.
+ (__in_place, __in_place_type, __in_place_index): Remove.
+ (in_place): Turn into an inline variable of non-reference
+ tag type.
+ (in_place<_Tp>): Remove.
+ (in_place_index<_Idx>): Remove.
+ (in_place_type_t): New.
+ (in_place_type): Turn into a variable template of non-reference
+ type.
+ (in_place_index_t): New.
+ (in_place_index): Turn into a variable template of non-reference
+ type.
+ * include/std/variant
+ (_Variant_storage(in_place_index_t<_Np>, _Args&&...)): Adjust to
+ use the new tag type.
+ (_Union(in_place_index_t<0>, _Args&&...)): Likewise.
+ (_Union(in_place_index_t<_Np>, _Args&&...)): Likewise.
+ (_Variant_base()): Likewise.
+ (variant(_Tp&&)): Likewise.
+ (variant(in_place_type_t<_Tp>, _Args&&...)): Likewise.
+ (variant(in_place_type_t<_Tp>, initializer_list<_Up>,
+ _Args&&...)): Likewise.
+ (variant(in_place_index_t<_Np>, _Args&&...)): Likewise.
+ (variant(in_place_index_t<_Np>, initializer_list<_Up>,
+ _Args&&...)): Likewise
+ (variant(allocator_arg_t, const _Alloc&)): Likewise.
+ (variant(allocator_arg_t, const _Alloc&, _Tp&&)): Likewise.
+ (variant(allocator_arg_t, const _Alloc&, in_place_type_t<_Tp>,
+ _Args&&...)): Likewise.
+ (variant(allocator_arg_t, const _Alloc&, in_place_type_t<_Tp>,
+ initializer_list<_Up>, _Args&&...)): Likewise.
+ (variant(allocator_arg_t, const _Alloc&, in_place_index_t<_Np>,
+ _Args&&...)): Likewise.
+ (variant(allocator_arg_t, const _Alloc&, in_place_index_t<_Np>,
+ initializer_list<_Up>, _Args&&...)): Likewise.
+ (emplace(_Args&&...)): Likewise.
+ (emplace(initializer_list<_Up>, _Args&&...)): Likewise.
+ * testsuite/20_util/any/cons/explicit.cc: Likewise.
+ * testsuite/20_util/any/cons/in_place.cc: Likewise.
+ * testsuite/20_util/any/requirements.cc: Add tests to
+ check that any is not constructible from the new in_place_type_t
+ of any value category.
+ * testsuite/20_util/in_place/requirements.cc: Adjust to
+ use the new tag type.
+ * testsuite/20_util/variant/compile.cc: Likewise.
+ * testsuite/20_util/variant/run.cc: Likewise.
+
2016-11-14 Ville Voutilainen <ville.voutilainen@gmail.com>
Use constexpr addressof in optional, SFINAE housekeeping
template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
typename _Mgr = _Manager<_Tp>,
__any_constructible_t<_Tp, _ValueType&&> = true,
- enable_if_t<!__is_in_place_type<_ValueType>::value, bool> = true>
+ enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true>
any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage)
{
typename _Mgr = _Manager<_Tp>,
enable_if_t<__and_<is_copy_constructible<_Tp>,
__not_<is_constructible<_Tp, _ValueType&&>>,
- __not_<__is_in_place_type<_ValueType>>>::value,
+ __not_<__is_in_place_type<_Tp>>>::value,
bool> = false>
any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage)
template <typename _Tp, typename... _Args>
any make_any(_Args&&... __args)
{
- return any(in_place<_Tp>, std::forward<_Args>(__args)...);
+ return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
}
/// Create an any holding a @c _Tp constructed from @c __il and @c __args.
template <typename _Tp, typename _Up, typename... _Args>
any make_any(initializer_list<_Up> __il, _Args&&... __args)
{
- return any(in_place<_Tp>, __il, std::forward<_Args>(__args)...);
+ return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
}
/**
#if __cplusplus > 201402L
- struct in_place_tag {
- in_place_tag() = delete;
+ struct in_place_t {
+ explicit in_place_t() = default;
};
- struct __in_place;
- template<typename _Tp> struct __in_place_type;
- template<size_t _Idx> struct __in_place_index;
-
- using in_place_t = in_place_tag(&)(__in_place*);
- template <class _Tp>
- using in_place_type_t = in_place_tag(&)(__in_place_type<_Tp>*);
- template <int _Idx>
- using in_place_index_t = in_place_tag(&)(__in_place_index<_Idx>*);
-
- inline in_place_tag in_place(__in_place*) {terminate();}
- template <class _Tp>
- in_place_tag in_place(__in_place_type<_Tp>*) {terminate();}
- template <size_t _Idx>
- in_place_tag in_place(__in_place_index<_Idx>*) {terminate();}
+ inline constexpr in_place_t in_place{};
+
+ template<typename _Tp> struct in_place_type_t
+ {
+ explicit in_place_type_t() = default;
+ };
+
+ template<typename _Tp>
+ inline constexpr in_place_type_t<_Tp> in_place_type{};
+
+ template<size_t _Idx> struct in_place_index_t
+ {
+ explicit in_place_index_t() = default;
+ };
+
+ template<size_t _Idx>
+ inline constexpr in_place_index_t<_Idx> in_place_index{};
template<typename>
struct __is_in_place_type_impl : false_type
template<size_t _Np, typename... _Args>
constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
- : _M_union(in_place<_Np>, std::forward<_Args>(__args)...)
+ : _M_union(in_place_index<_Np>, std::forward<_Args>(__args)...)
{ }
~_Variant_storage() = default;
template<typename... _Args>
constexpr _Union(in_place_index_t<0>, _Args&&... __args)
- : _M_first(in_place<0>, std::forward<_Args>(__args)...)
+ : _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
{ }
template<size_t _Np, typename... _Args,
typename = enable_if_t<0 < _Np && _Np < sizeof...(_Rest) + 1>>
constexpr _Union(in_place_index_t<_Np>, _Args&&... __args)
- : _M_rest(in_place<_Np - 1>, std::forward<_Args>(__args)...)
+ : _M_rest(in_place_index<_Np - 1>, std::forward<_Args>(__args)...)
{ }
_Uninitialized<__storage<_First>> _M_first;
_Variant_base()
noexcept(is_nothrow_default_constructible_v<
variant_alternative_t<0, variant<_Types...>>>)
- : _Variant_base(in_place<0>) { }
+ : _Variant_base(in_place_index<0>) { }
_Variant_base(const _Variant_base& __rhs)
: _Storage(), _M_index(__rhs._M_index)
constexpr
variant(_Tp&& __t)
noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
- : variant(in_place<__accepted_index<_Tp&&>>, std::forward<_Tp>(__t))
+ : variant(in_place_index<__accepted_index<_Tp&&>>, std::forward<_Tp>(__t))
{ __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); }
template<typename _Tp, typename... _Args,
&& is_constructible_v<_Tp, _Args&&...>>>
constexpr explicit
variant(in_place_type_t<_Tp>, _Args&&... __args)
- : variant(in_place<__index_of<_Tp>>, std::forward<_Args>(__args)...)
+ : variant(in_place_index<__index_of<_Tp>>, std::forward<_Args>(__args)...)
{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
template<typename _Tp, typename _Up, typename... _Args,
constexpr explicit
variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
_Args&&... __args)
- : variant(in_place<__index_of<_Tp>>, __il,
+ : variant(in_place_index<__index_of<_Tp>>, __il,
std::forward<_Args>(__args)...)
{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
is_constructible_v<__to_type<_Np>, _Args&&...>>>
constexpr explicit
variant(in_place_index_t<_Np>, _Args&&... __args)
- : _Base(in_place<_Np>, std::forward<_Args>(__args)...),
+ : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),
_Default_ctor_enabler(_Enable_default_constructor_tag{})
{ __glibcxx_assert(index() == _Np); }
constexpr explicit
variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
_Args&&... __args)
- : _Base(in_place<_Np>, __il, std::forward<_Args>(__args)...),
+ : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...),
_Default_ctor_enabler(_Enable_default_constructor_tag{})
{ __glibcxx_assert(index() == _Np); }
typename = enable_if_t<
__is_uses_allocator_constructible_v<__to_type<0>, _Alloc>>>
variant(allocator_arg_t, const _Alloc& __a)
- : variant(allocator_arg, __a, in_place<0>)
+ : variant(allocator_arg, __a, in_place_index<0>)
{ }
template<typename _Alloc,
__accepted_type<_Tp&&>, _Alloc, _Tp&&>
&& !is_same_v<decay_t<_Tp>, variant>, variant&>>
variant(allocator_arg_t, const _Alloc& __a, _Tp&& __t)
- : variant(allocator_arg, __a, in_place<__accepted_index<_Tp&&>>,
+ : variant(allocator_arg, __a, in_place_index<__accepted_index<_Tp&&>>,
std::forward<_Tp>(__t))
{ __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); }
_Tp, _Alloc, _Args&&...>>>
variant(allocator_arg_t, const _Alloc& __a, in_place_type_t<_Tp>,
_Args&&... __args)
- : variant(allocator_arg, __a, in_place<__index_of<_Tp>>,
+ : variant(allocator_arg, __a, in_place_index<__index_of<_Tp>>,
std::forward<_Args>(__args)...)
{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
_Tp, _Alloc, initializer_list<_Up>&, _Args&&...>>>
variant(allocator_arg_t, const _Alloc& __a, in_place_type_t<_Tp>,
initializer_list<_Up> __il, _Args&&... __args)
- : variant(allocator_arg, __a, in_place<__index_of<_Tp>>, __il,
+ : variant(allocator_arg, __a, in_place_index<__index_of<_Tp>>, __il,
std::forward<_Args>(__args)...)
{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
__to_type<_Np>, _Alloc, _Args&&...>>>
variant(allocator_arg_t, const _Alloc& __a, in_place_index_t<_Np>,
_Args&&... __args)
- : _Base(__a, in_place<_Np>, std::forward<_Args>(__args)...),
+ : _Base(__a, in_place_index<_Np>, std::forward<_Args>(__args)...),
_Default_ctor_enabler(_Enable_default_constructor_tag{})
{ __glibcxx_assert(index() == _Np); }
__to_type<_Np>, _Alloc, initializer_list<_Up>&, _Args&&...>>>
variant(allocator_arg_t, const _Alloc& __a, in_place_index_t<_Np>,
initializer_list<_Up> __il, _Args&&... __args)
- : _Base(__a, in_place<_Np>, __il, std::forward<_Args>(__args)...),
+ : _Base(__a, in_place_index<_Np>, __il, std::forward<_Args>(__args)...),
_Default_ctor_enabler(_Enable_default_constructor_tag{})
{ __glibcxx_assert(index() == _Np); }
this->~variant();
__try
{
- ::new (this) variant(in_place<_Np>,
+ ::new (this) variant(in_place_index<_Np>,
std::forward<_Args>(__args)...);
}
__catch (...)
this->~variant();
__try
{
- ::new (this) variant(in_place<_Np>, __il,
+ ::new (this) variant(in_place_index<_Np>, __il,
std::forward<_Args>(__args)...);
}
__catch (...)
int main()
{
- std::any a = {std::in_place<int>, 42}; // { dg-error "converting" }
- std::any a2 =
- {std::in_place<std::vector<int>>, {42, 666}}; // { dg-error "converting" }
+ std::any a = {std::in_place_type<int>, 42}; // { dg-error "converting" }
+ std::any a2 = {std::in_place_type<std::vector<int>>,
+ {42, 666}}; // { dg-error "converting" }
}
int main()
{
const int i = 42;
- std::any o(std::in_place<int>, i);
+ std::any o(std::in_place_type<int>, i);
int& i2 = std::any_cast<int&>(o);
VERIFY( i2 == 42 );
VERIFY( &i2 != &i );
- std::any o2(std::in_place<std::tuple<int, int>>, 1, 2);
+ std::any o2(std::in_place_type<std::tuple<int, int>>, 1, 2);
std::tuple<int, int>& t = std::any_cast<std::tuple<int, int>&>(o2);
VERIFY( std::get<0>(t) == 1 && std::get<1>(t) == 2);
- std::any o3(std::in_place<std::vector<int>>, {42, 666});
+ std::any o3(std::in_place_type<std::vector<int>>, {42, 666});
std::vector<int>& v = std::any_cast<std::vector<int>&>(o3);
VERIFY(v[0] == 42 && v[1] == 666);
- std::any o4(std::in_place<combined>, {42, 666});
+ std::any o4(std::in_place_type<combined>, {42, 666});
combined& c = std::any_cast<combined&>(o4);
VERIFY(c.v[0] == 42 && c.v[1] == 666
&& std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
- std::any o5(std::in_place<combined>, {1, 2}, 3, 4);
+ std::any o5(std::in_place_type<combined>, {1, 2}, 3, 4);
combined& c2 = std::any_cast<combined&>(o5);
VERIFY(c2.v[0] == 1 && c2.v[1] == 2
&& std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
- std::any o6(std::in_place<int&>, i);
+ std::any o6(std::in_place_type<int&>, i);
VERIFY(o6.type() == o.type());
- std::any o7(std::in_place<void()>, nullptr);
- std::any o8(std::in_place<void(*)()>, nullptr);
+ std::any o7(std::in_place_type<void()>, nullptr);
+ std::any o8(std::in_place_type<void(*)()>, nullptr);
VERIFY(o7.type() == o8.type());
- std::any o9(std::in_place<char(&)[42]>, nullptr);
- std::any o10(std::in_place<char*>, nullptr);
+ std::any o9(std::in_place_type<char(&)[42]>, nullptr);
+ std::any o10(std::in_place_type<char*>, nullptr);
VERIFY(o9.type() == o10.type());
}
static_assert(!std::is_constructible<any,
std::in_place_type_t<NoDefaultCtor>>::value);
+
+static_assert(!std::is_constructible<any,
+ std::in_place_type_t<NoDefaultCtor>&>::value);
+
+static_assert(!std::is_constructible<any,
+ std::in_place_type_t<NoDefaultCtor>&&>::value);
+
+static_assert(!std::is_constructible<any,
+ const std::in_place_type_t<NoDefaultCtor>&>::value);
+
+static_assert(!std::is_constructible<any,
+ const std::in_place_type_t<NoDefaultCtor>&&>::value);
unsigned int f(in_place_index_t<1>);
int f(in_place_t);
-static_assert(std::is_same<decltype(f(in_place_t(std::in_place))), int>::value);
-static_assert(std::is_same<decltype(f(std::in_place<float>)), float>::value);
-static_assert(std::is_same<decltype(f(std::in_place<double>)), double>::value);
-static_assert(std::is_same<decltype(f(std::in_place<0>)), char>::value);
-static_assert(std::is_same<decltype(f(std::in_place<1>)), unsigned int>::value);
+static_assert(std::is_same<decltype(f(std::in_place)), int>::value);
+static_assert(std::is_same<decltype(f(std::in_place_type<float>)),
+ float>::value);
+static_assert(std::is_same<decltype(f(std::in_place_type<double>)),
+ double>::value);
+static_assert(std::is_same<decltype(f(std::in_place_index<0>)), char>::value);
+static_assert(std::is_same<decltype(f(std::in_place_index<1>)),
+ unsigned int>::value);
template <class T, class... Args> float h(in_place_type_t<T>, Args&&...);
template <size_t N, class... Args> int h(in_place_index_t<N>, Args&&...);
template <class T> double h(in_place_t, T&&);
static_assert(std::is_same<decltype(h(std::in_place, 1)), double>::value);
-static_assert(std::is_same<decltype(h(std::in_place<float>, 1)), float>::value);
-static_assert(std::is_same<decltype(h(std::in_place<0>, 1)), int>::value);
+static_assert(std::is_same<decltype(h(std::in_place_type<float>, 1)),
+ float>::value);
+static_assert(std::is_same<decltype(h(std::in_place_index<0>, 1)),
+ int>::value);
void in_place_index_ctor()
{
- variant<string, string> a(in_place<0>, "a");
- variant<string, string> b(in_place<1>, {'a'});
+ variant<string, string> a(in_place_index<0>, "a");
+ variant<string, string> b(in_place_index<1>, {'a'});
}
void in_place_type_ctor()
{
- variant<int, string, int> a(in_place<string>, "a");
- variant<int, string, int> b(in_place<string>, {'a'});
+ variant<int, string, int> a(in_place_type<string>, "a");
+ variant<int, string, int> b(in_place_type<string>, {'a'});
static_assert(!is_constructible_v<variant<string, string>, in_place_type_t<string>, const char*>, "");
}
static_assert(!is_constructible_v<variant<string, string>, allocator_arg_t, std::allocator<char>, const char*>, "");
}
{
- variant<string, int> b(allocator_arg, alloc, in_place<0>, "a");
- variant<string, string> c(allocator_arg, alloc, in_place<1>, "a");
+ variant<string, int> b(allocator_arg, alloc, in_place_index<0>, "a");
+ variant<string, string> c(allocator_arg, alloc, in_place_index<1>, "a");
}
{
- variant<string, int> b(allocator_arg, alloc, in_place<0>, {'a'});
- variant<string, string> c(allocator_arg, alloc, in_place<1>, {'a'});
+ variant<string, int> b(allocator_arg, alloc, in_place_index<0>, {'a'});
+ variant<string, string> c(allocator_arg, alloc, in_place_index<1>, {'a'});
}
{
- variant<int, string, int> b(allocator_arg, alloc, in_place<string>, "a");
+ variant<int, string, int> b(allocator_arg, alloc, in_place_type<string>, "a");
}
{
- variant<int, string, int> b(allocator_arg, alloc, in_place<string>, {'a'});
+ variant<int, string, int> b(allocator_arg, alloc, in_place_type<string>, {'a'});
}
}
{
constexpr variant<int> a;
static_assert(holds_alternative<int>(a), "");
- constexpr variant<int, char> b(in_place<0>, int{});
+ constexpr variant<int, char> b(in_place_index<0>, int{});
static_assert(holds_alternative<int>(b), "");
- constexpr variant<int, char> c(in_place<int>, int{});
+ constexpr variant<int, char> c(in_place_type<int>, int{});
static_assert(holds_alternative<int>(c), "");
- constexpr variant<int, char> d(in_place<1>, char{});
+ constexpr variant<int, char> d(in_place_index<1>, char{});
static_assert(holds_alternative<char>(d), "");
- constexpr variant<int, char> e(in_place<char>, char{});
+ constexpr variant<int, char> e(in_place_type<char>, char{});
static_assert(holds_alternative<char>(e), "");
constexpr variant<int, char> f(char{});
static_assert(holds_alternative<char>(f), "");
};
constexpr variant<literal, nonliteral> v{};
- constexpr variant<literal, nonliteral> v1{in_place<literal>};
- constexpr variant<literal, nonliteral> v2{in_place<0>};
+ constexpr variant<literal, nonliteral> v1{in_place_type<literal>};
+ constexpr variant<literal, nonliteral> v2{in_place_index<0>};
}
}
v0.emplace<0>(x);
v0.emplace<0>(il, x);
visit(vis, v0);
- variant<X> v1{in_place<0>, x};
- variant<X> v2{in_place<X>, x};
- variant<X> v3{in_place<0>, il, x};
- variant<X> v4{in_place<X>, il, x};
- variant<X> v5{allocator_arg, a, in_place<0>, x};
- variant<X> v6{allocator_arg, a, in_place<X>, x};
- variant<X> v7{allocator_arg, a, in_place<0>, il, x};
- variant<X> v8{allocator_arg, a, in_place<X>, il, x};
- variant<X> v9{allocator_arg, a, in_place<X>, 1};
+ variant<X> v1{in_place_index<0>, x};
+ variant<X> v2{in_place_type<X>, x};
+ variant<X> v3{in_place_index<0>, il, x};
+ variant<X> v4{in_place_type<X>, il, x};
+ variant<X> v5{allocator_arg, a, in_place_index<0>, x};
+ variant<X> v6{allocator_arg, a, in_place_type<X>, x};
+ variant<X> v7{allocator_arg, a, in_place_index<0>, il, x};
+ variant<X> v8{allocator_arg, a, in_place_type<X>, il, x};
+ variant<X> v9{allocator_arg, a, in_place_type<X>, 1};
std::variant<X&> vr0(x);
vr0 = x;
- variant<X&> vr1{in_place<0>, x};
- variant<X&> vr2{in_place<X&>, x};
- variant<X&> vr3{allocator_arg, a, in_place<0>, x};
- variant<X&> vr4{allocator_arg, a, in_place<X&>, x};
+ variant<X&> vr1{in_place_index<0>, x};
+ variant<X&> vr2{in_place_type<X&>, x};
+ variant<X&> vr3{allocator_arg, a, in_place_index<0>, x};
+ variant<X&> vr4{allocator_arg, a, in_place_type<X&>, x};
}
};
{
int called = 0;
- { variant<string, A> a(in_place<1>, called); }
+ { variant<string, A> a(in_place_index<1>, called); }
VERIFY(called == 1);
}
{
int called = 0;
- { variant<string, A> a(in_place<0>); }
+ { variant<string, A> a(in_place_index<0>); }
VERIFY(called == 0);
}
}
void in_place_index_ctor()
{
{
- variant<int, string> v(in_place<1>, "a");
+ variant<int, string> v(in_place_index<1>, "a");
VERIFY(holds_alternative<string>(v));
VERIFY(get<1>(v) == "a");
}
{
- variant<int, string> v(in_place<1>, {'a', 'b'});
+ variant<int, string> v(in_place_index<1>, {'a', 'b'});
VERIFY(holds_alternative<string>(v));
VERIFY(get<1>(v) == "ab");
}
void in_place_type_ctor()
{
{
- variant<int, string> v(in_place<string>, "a");
+ variant<int, string> v(in_place_type<string>, "a");
VERIFY(holds_alternative<string>(v));
VERIFY(get<1>(v) == "a");
}
{
- variant<int, string> v(in_place<string>, {'a', 'b'});
+ variant<int, string> v(in_place_type<string>, {'a', 'b'});
VERIFY(holds_alternative<string>(v));
VERIFY(get<1>(v) == "ab");
}