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
This commit is contained in:
@@ -171,6 +171,20 @@ template<class... T>
|
|||||||
|
|
||||||
template<class T, class U=T>
|
template<class T, class U=T>
|
||||||
T exchange(T& obj, U&& new_value);
|
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
|
} // std
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -179,6 +193,7 @@ template<class T, class U=T>
|
|||||||
#include <__tuple>
|
#include <__tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <__debug>
|
||||||
|
|
||||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||||
#pragma GCC system_header
|
#pragma GCC system_header
|
||||||
@@ -782,6 +797,49 @@ _T1 exchange(_T1& __obj, _T2 && __new_value)
|
|||||||
}
|
}
|
||||||
#endif // _LIBCPP_STD_VER > 11
|
#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
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
#endif // _LIBCPP_UTILITY
|
#endif // _LIBCPP_UTILITY
|
||||||
|
|||||||
99
test/std/utilities/utility/utility.inplace/inplace.pass.cpp
Normal file
99
test/std/utilities/utility/utility.inplace/inplace.pass.cpp
Normal file
@@ -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, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user