On 15 August 2016 at 14:55, Ville Voutilainen <ville.voutilai...@gmail.com> wrote: >>> + template<typename _Tp> >>> + struct __is_in_place >>> + : public >>> __is_in_place_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>> >> >> >> Any reason not to use decay_t here? In all the cases where decay is >> different to stripping references and cv-qualifiers the result will be >> false either way. >> >> I wouldn't have bothered with the std:: qualification either, but it's >> fine as it is. > > > The reason for not using decay and for the qualification is that the > trait is closely > related to its copy-paste origin, which is __is_optional. ;) I should > also add a test > for the case where in_place is attempted to pass through the > ValueType&& parameter, > aka a case where a type is not default-constructible but is > constructible from in_place, > and in_place-construction is used.
Argh, the trait shouldn't either decay or remove_reference, and the remove_const is superfluous. These tags are references to functions, decaying them will cause bad mojo. Now that I actually test that the in_place avoidance in the perfect forwarder works, it's fixed. Tested on Linux-x64. 2016-08-15 Ville Voutilainen <ville.voutilai...@gmail.com> Implement LWG 2744 and LWG 2754. * include/std/any (any(ValueType&&)): Constrain with __is_in_place_type. (any(in_place_type_t<_ValueType>, _Args&&...)): Use _Decay. (any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&...)): Likewise. (emplace(_Args&&...)): Likewise. (emplace(initializer_list<_Up>, _Args&&...)): Likewise. * include/std/utility: (__is_in_place_type_impl): New. (__is_in_place_type): Likewise. * testsuite/20_util/any/assign/emplace.cc: Add tests for decaying emplace. * testsuite/20_util/any/cons/in_place.cc: Add tests for decaying in_place constructor. * testsuite/20_util/any/misc/any_cast_neg.cc: Adjust. * testsuite/20_util/any/requirements.cc: Add a test for in_place-constructing a non-default-constructible type.
diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index 4add118..9160035 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -153,7 +153,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Construct with a copy of @p __value as the contained object. template <typename _ValueType, typename _Tp = _Decay<_ValueType>, typename _Mgr = _Manager<_Tp>, - __any_constructible_t<_Tp, _ValueType&&> = true> + __any_constructible_t<_Tp, _ValueType&&> = true, + enable_if_t<!__is_in_place_type<_ValueType>::value, bool> = true> any(_ValueType&& __value) : _M_manager(&_Mgr::_S_manage) { @@ -164,9 +165,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _ValueType, typename _Tp = _Decay<_ValueType>, typename _Mgr = _Manager<_Tp>, enable_if_t<__and_<is_copy_constructible<_Tp>, - __not_< - is_constructible<_Tp, - _ValueType&&>>>::value, + __not_<is_constructible<_Tp, _ValueType&&>>, + __not_<__is_in_place_type<_ValueType>>>::value, bool> = false> any(_ValueType&& __value) : _M_manager(&_Mgr::_S_manage) @@ -175,10 +175,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Construct with an object created from @p __args as the contained object. - template <typename _Tp, typename... _Args, + template <typename _ValueType, typename... _Args, + typename _Tp = _Decay<_ValueType>, typename _Mgr = _Manager<_Tp>, __any_constructible_t<_Tp, _Args&&...> = false> - any(in_place_type_t<_Tp>, _Args&&... __args) + any(in_place_type_t<_ValueType>, _Args&&... __args) : _M_manager(&_Mgr::_S_manage) { _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); @@ -186,11 +187,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Construct with an object created from @p __il and @p __args as /// the contained object. - template <typename _Tp, typename _Up, typename... _Args, + template <typename _ValueType, typename _Up, typename... _Args, + typename _Tp = _Decay<_ValueType>, typename _Mgr = _Manager<_Tp>, __any_constructible_t<_Tp, initializer_list<_Up>, _Args&&...> = false> - any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) + any(in_place_type_t<_ValueType>, + initializer_list<_Up> __il, _Args&&... __args) : _M_manager(&_Mgr::_S_manage) { _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); @@ -248,7 +251,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Emplace with an object created from @p __args as the contained object. - template <typename _Tp, typename... _Args, + template <typename _ValueType, typename... _Args, + typename _Tp = _Decay<_ValueType>, typename _Mgr = _Manager<_Tp>, __any_constructible_t<_Tp, _Args&&...> = false> void emplace(_Args&&... __args) @@ -260,7 +264,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Emplace with an object created from @p __il and @p __args as /// the contained object. - template <typename _Tp, typename _Up, typename... _Args, + template <typename _ValueType, typename _Up, typename... _Args, + typename _Tp = _Decay<_ValueType>, typename _Mgr = _Manager<_Tp>, __any_constructible_t<_Tp, initializer_list<_Up>, _Args&&...> = false> diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 0c03644..6a6659b 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -356,6 +356,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <size_t _Idx> in_place_tag in_place(__in_place_index<_Idx>*) {terminate();} + template<typename> + struct __is_in_place_type_impl : false_type + { }; + + template<typename _Tp> + struct __is_in_place_type_impl<in_place_type_t<_Tp>> : true_type + { }; + + template<typename _Tp> + struct __is_in_place_type + : public __is_in_place_type_impl<_Tp> + { }; + #define __cpp_lib_as_const 201510 template<typename _Tp> constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } @@ -363,7 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> void as_const(const _Tp&&) = delete; -#endif +#endif // C++17 _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc b/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc index 663bae2..799c5ed 100644 --- a/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc +++ b/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc @@ -59,4 +59,17 @@ int main() 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; + o6.emplace<const int&>(i); + VERIFY(o6.type() == o.type()); + std::any o7; + o7.emplace<void()>(nullptr); + std::any o8; + o8.emplace<void(*)()>(nullptr); + VERIFY(o7.type() == o8.type()); + std::any o9; + o9.emplace<char(&)[42]>(nullptr); + std::any o10; + o10.emplace<char*>(nullptr); + VERIFY(o9.type() == o10.type()); } diff --git a/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc b/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc index 2368b83..52f2b38 100644 --- a/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc +++ b/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc @@ -54,4 +54,12 @@ int main() 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); + VERIFY(o6.type() == o.type()); + std::any o7(std::in_place<void()>, nullptr); + std::any o8(std::in_place<void(*)()>, nullptr); + VERIFY(o7.type() == o8.type()); + std::any o9(std::in_place<char(&)[42]>, nullptr); + std::any o10(std::in_place<char*>, nullptr); + VERIFY(o9.type() == o10.type()); } diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc index 32b4e76..05fdeb7 100644 --- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc @@ -26,5 +26,5 @@ void test01() using std::any_cast; const any y(1); - any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 435 } + any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 440 } } diff --git a/libstdc++-v3/testsuite/20_util/any/requirements.cc b/libstdc++-v3/testsuite/20_util/any/requirements.cc index f33cd67..7b084be 100644 --- a/libstdc++-v3/testsuite/20_util/any/requirements.cc +++ b/libstdc++-v3/testsuite/20_util/any/requirements.cc @@ -34,3 +34,11 @@ static_assert(!std::is_assignable<any&, const unique_ptr<int>&>::value); static_assert(!std::is_constructible<any&, const unique_ptr<int>&>::value); static_assert(!std::is_assignable<any&, unique_ptr<int>&>::value); static_assert(!std::is_constructible<any&, unique_ptr<int>&>::value); + +struct NoDefaultCtor +{ + NoDefaultCtor() = delete; +}; + +static_assert(!std::is_constructible<any, + std::in_place_type_t<NoDefaultCtor>>::value);