Author: ericwf Date: Sat Jul 23 17:19:19 2016 New Revision: 276537 URL: http://llvm.org/viewvc/llvm-project?rev=276537&view=rev Log: Implement the in_place tags from p0032r3.
That paper also has changes to any/optional but those will be implemented later. Added: libcxx/trunk/test/std/utilities/utility/utility.inplace/ libcxx/trunk/test/std/utilities/utility/utility.inplace/inplace.pass.cpp Modified: libcxx/trunk/include/utility Modified: libcxx/trunk/include/utility URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?rev=276537&r1=276536&r2=276537&view=diff ============================================================================== --- libcxx/trunk/include/utility (original) +++ libcxx/trunk/include/utility Sat Jul 23 17:19:19 2016 @@ -171,6 +171,20 @@ template<class... T> template<class T, class U=T> T exchange(T& obj, U&& new_value); + +// 20.2.7, in-place construction // C++17 +struct in_place_tag { in_place_tag() = delete; }; // C++17 +using in_place_t = in_place_tag(&)(unspecified ); +template <class T> + using in_place_type_t = in_place_tag(&)(unspecified <T>); +template <size_t I> + using in_place_index_t = in_place_tag(&)(unspecified <I>); +in_place_tag in_place(unspecified ); +template <class T> + in_place_tag in_place(unspecified <T>); +template <size_t I> + in_place_tag in_place(unspecified <I>); + } // std */ @@ -179,6 +193,7 @@ template<class T, class U=T> #include <__tuple> #include <type_traits> #include <initializer_list> +#include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -782,6 +797,49 @@ _T1 exchange(_T1& __obj, _T2 && __new_va } #endif // _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER > 14 + +struct _LIBCPP_TYPE_VIS_ONLY __in_place_tag {}; +template <class> struct _LIBCPP_TYPE_VIS_ONLY __in_place_type_tag {}; +template <size_t> struct _LIBCPP_TYPE_VIS_ONLY __in_place_index_tag {}; + +struct _LIBCPP_TYPE_VIS_ONLY in_place_tag; + +using in_place_t = in_place_tag(&)(__in_place_tag); +template <class _Tp> +using in_place_type_t = in_place_tag(&)(__in_place_type_tag<_Tp>); +template <size_t _Nx> +using in_place_index_t = in_place_tag(&)(__in_place_index_tag<_Nx>); + +struct in_place_tag { + in_place_tag() = delete; +private: + explicit in_place_tag(__in_place_tag) {} + + friend inline in_place_tag in_place(__in_place_tag __t); + template <class _Tp> + friend inline in_place_tag in_place(__in_place_type_tag<_Tp>); + template <size_t _Nx> + friend inline in_place_tag in_place(__in_place_index_tag<_Nx>); +}; + +inline in_place_tag in_place(__in_place_tag __t) { + _LIBCPP_ASSERT(false, "The in_place function cannot be invoked"); + return in_place_tag(__t); +} +template <class _Tp> +inline in_place_tag in_place(__in_place_type_tag<_Tp>) { + _LIBCPP_ASSERT(false, "The in_place function cannot be invoked"); + return in_place_tag(__in_place_tag{}); +} +template <size_t _Nx> +inline in_place_tag in_place(__in_place_index_tag<_Nx>) { + _LIBCPP_ASSERT(false, "The in_place function cannot be invoked"); + return in_place_tag(__in_place_tag{}); +} + +#endif // _LIBCPP_STD_VER > 14 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_UTILITY Added: libcxx/trunk/test/std/utilities/utility/utility.inplace/inplace.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/utility.inplace/inplace.pass.cpp?rev=276537&view=auto ============================================================================== --- libcxx/trunk/test/std/utilities/utility/utility.inplace/inplace.pass.cpp (added) +++ libcxx/trunk/test/std/utilities/utility/utility.inplace/inplace.pass.cpp Sat Jul 23 17:19:19 2016 @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <utility> + +// struct in_place_tag { in_place_tag() = delete; }; +// +// using in_place_t = in_place_tag(&)(unspecified); +// template <class T> +// using in_place_type_t = in_place_tag(&)(unspecified<T>); +// template <size_t N> +// using in_place_index_t = in_place_tag(&)(unspecified<N>); +// +// in_place_tag in_place(unspecified); +// +// template <class T>; +// in_place_tag in_place(unspecified<T>); +// +// template <size_t N> +// in_place_tag in_place(unspecified<N>); + +#include <utility> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "type_id.h" + +template <class Tp> +struct CheckRet : std::false_type {}; +template <class Arg> +struct CheckRet<std::in_place_tag(Arg)> : std::true_type {}; + +TypeID const* test_fn(std::in_place_t) { return &makeTypeID<std::in_place_t>(); } +template <class T> +TypeID const* test_fn(std::in_place_type_t<T>) +{ return &makeTypeID<std::in_place_type_t<T>>(); } + +template <size_t I> +TypeID const* test_fn(std::in_place_index_t<I>) +{ return &makeTypeID<std::in_place_index_t<I>>(); } + +// Concrete test overloads that don't have to be deduced. +template <class Tag> +TypeID const* concrete_test_fn(Tag) { return &makeTypeID<Tag>(); } + +template <class Tp> +bool check_tag_basic() { + using RawTp = typename std::remove_reference<Tp>::type; + static_assert(std::is_lvalue_reference<Tp>::value, ""); + static_assert(std::is_function<RawTp>::value, ""); + static_assert(CheckRet<RawTp>::value, ""); + auto concrete_fn = concrete_test_fn<Tp>; + return test_fn((Tp)std::in_place) == &makeTypeID<Tp>() + && concrete_fn(std::in_place) == &makeTypeID<Tp>(); +} + +int main() { + // test in_place_tag + { + static_assert(!std::is_default_constructible<std::in_place_tag>::value, ""); + } + // test in_place_t + { + using T = std::in_place_t; + assert(check_tag_basic<std::in_place_t>()); + assert(test_fn((T)std::in_place) == &makeTypeID<T>()); + } + // test in_place_type_t + { + using T1 = std::in_place_type_t<void>; + using T2 = std::in_place_type_t<int>; + using T3 = std::in_place_type_t<const int>; + assert(check_tag_basic<T1>()); + assert(check_tag_basic<T2>()); + assert(check_tag_basic<T3>()); + static_assert(!std::is_same<T1, T2>::value && !std::is_same<T1, T3>::value, ""); + static_assert(!std::is_same<T2, T3>::value, ""); + } + // test in_place_index_t + { + using T1 = std::in_place_index_t<0>; + using T2 = std::in_place_index_t<1>; + using T3 = std::in_place_index_t<static_cast<size_t>(-1)>; + assert(check_tag_basic<T1>()); + assert(check_tag_basic<T2>()); + assert(check_tag_basic<T3>()); + static_assert(!std::is_same<T1, T2>::value && !std::is_same<T1, T3>::value, ""); + static_assert(!std::is_same<T2, T3>::value, ""); + } +} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits