[libcxx] r276537 - Implement the in_place tags from p0032r3.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sat Jul 23 15:19:20 PDT 2016


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




More information about the cfe-commits mailing list