From eef85d904452972fff7a23d31718e2821d014008 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sat, 23 Jul 2016 22:19:19 +0000 Subject: [PATCH] Implement the in_place tags from p0032r3. That paper also has changes to any/optional but those will be implemented later. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@276537 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/utility | 58 +++++++++++ .../utility/utility.inplace/inplace.pass.cpp | 99 +++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 test/std/utilities/utility/utility.inplace/inplace.pass.cpp diff --git a/include/utility b/include/utility index 7b978ad30..fd8a7f2fc 100644 --- a/include/utility +++ b/include/utility @@ -171,6 +171,20 @@ template template 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 + using in_place_type_t = in_place_tag(&)(unspecified ); +template + using in_place_index_t = in_place_tag(&)(unspecified ); +in_place_tag in_place(unspecified ); +template + in_place_tag in_place(unspecified ); +template + in_place_tag in_place(unspecified ); + } // std */ @@ -179,6 +193,7 @@ template #include <__tuple> #include #include +#include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -782,6 +797,49 @@ _T1 exchange(_T1& __obj, _T2 && __new_value) } #endif // _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER > 14 + +struct _LIBCPP_TYPE_VIS_ONLY __in_place_tag {}; +template struct _LIBCPP_TYPE_VIS_ONLY __in_place_type_tag {}; +template 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 +using in_place_type_t = in_place_tag(&)(__in_place_type_tag<_Tp>); +template +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 + friend inline in_place_tag in_place(__in_place_type_tag<_Tp>); + template + 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 +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 +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 diff --git a/test/std/utilities/utility/utility.inplace/inplace.pass.cpp b/test/std/utilities/utility/utility.inplace/inplace.pass.cpp new file mode 100644 index 000000000..0cf8e38f5 --- /dev/null +++ b/test/std/utilities/utility/utility.inplace/inplace.pass.cpp @@ -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 + +// + +// struct in_place_tag { in_place_tag() = delete; }; +// +// using in_place_t = in_place_tag(&)(unspecified); +// template +// using in_place_type_t = in_place_tag(&)(unspecified); +// template +// using in_place_index_t = in_place_tag(&)(unspecified); +// +// in_place_tag in_place(unspecified); +// +// template ; +// in_place_tag in_place(unspecified); +// +// template +// in_place_tag in_place(unspecified); + +#include +#include +#include + +#include "test_macros.h" +#include "type_id.h" + +template +struct CheckRet : std::false_type {}; +template +struct CheckRet : std::true_type {}; + +TypeID const* test_fn(std::in_place_t) { return &makeTypeID(); } +template +TypeID const* test_fn(std::in_place_type_t) +{ return &makeTypeID>(); } + +template +TypeID const* test_fn(std::in_place_index_t) +{ return &makeTypeID>(); } + +// Concrete test overloads that don't have to be deduced. +template +TypeID const* concrete_test_fn(Tag) { return &makeTypeID(); } + +template +bool check_tag_basic() { + using RawTp = typename std::remove_reference::type; + static_assert(std::is_lvalue_reference::value, ""); + static_assert(std::is_function::value, ""); + static_assert(CheckRet::value, ""); + auto concrete_fn = concrete_test_fn; + return test_fn((Tp)std::in_place) == &makeTypeID() + && concrete_fn(std::in_place) == &makeTypeID(); +} + +int main() { + // test in_place_tag + { + static_assert(!std::is_default_constructible::value, ""); + } + // test in_place_t + { + using T = std::in_place_t; + assert(check_tag_basic()); + assert(test_fn((T)std::in_place) == &makeTypeID()); + } + // test in_place_type_t + { + using T1 = std::in_place_type_t; + using T2 = std::in_place_type_t; + using T3 = std::in_place_type_t; + assert(check_tag_basic()); + assert(check_tag_basic()); + assert(check_tag_basic()); + static_assert(!std::is_same::value && !std::is_same::value, ""); + static_assert(!std::is_same::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(-1)>; + assert(check_tag_basic()); + assert(check_tag_basic()); + assert(check_tag_basic()); + static_assert(!std::is_same::value && !std::is_same::value, ""); + static_assert(!std::is_same::value, ""); + } +} \ No newline at end of file