[libcxx] r278300 - Implement LWG 2148: Make non-enum default hash specialization well-formed
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 10 15:45:26 PDT 2016
Author: ericwf
Date: Wed Aug 10 17:45:26 2016
New Revision: 278300
URL: http://llvm.org/viewvc/llvm-project?rev=278300&view=rev
Log:
Implement LWG 2148: Make non-enum default hash specialization well-formed
Summary:
This patch removes the static_assert for non-enum types in the primary hash template. Instead non-enum types create a hash<T> specialization that is not constructible nor callable.
See also:
* http://cplusplus.github.io/LWG/lwg-active.html#2543
* https://llvm.org/bugs/show_bug.cgi?id=28917
Reviewers: mclow.lists, EricWF
Subscribers: mehdi_amini, cfe-commits
Differential Revision: https://reviews.llvm.org/D23331
Added:
libcxx/trunk/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp
Modified:
libcxx/trunk/include/functional
libcxx/trunk/test/std/utilities/function.objects/unord.hash/enum.pass.cpp
Modified: libcxx/trunk/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=278300&r1=278299&r2=278300&view=diff
==============================================================================
--- libcxx/trunk/include/functional (original)
+++ libcxx/trunk/include/functional Wed Aug 10 17:45:26 2016
@@ -2574,12 +2574,11 @@ struct _LIBCPP_TYPE_VIS_ONLY hash<long d
};
#if _LIBCPP_STD_VER > 11
-template <class _Tp>
-struct _LIBCPP_TYPE_VIS_ONLY hash
+
+template <class _Tp, bool = is_enum<_Tp>::value>
+struct _LIBCPP_TYPE_VIS_ONLY __enum_hash
: public unary_function<_Tp, size_t>
{
- static_assert(is_enum<_Tp>::value, "This hash only works for enumeration types");
-
_LIBCPP_INLINE_VISIBILITY
size_t operator()(_Tp __v) const _NOEXCEPT
{
@@ -2587,6 +2586,17 @@ struct _LIBCPP_TYPE_VIS_ONLY hash
return hash<type>{}(static_cast<type>(__v));
}
};
+template <class _Tp>
+struct _LIBCPP_TYPE_VIS_ONLY __enum_hash<_Tp, false> {
+ __enum_hash() = delete;
+ __enum_hash(__enum_hash const&) = delete;
+ __enum_hash& operator=(__enum_hash const&) = delete;
+};
+
+template <class _Tp>
+struct _LIBCPP_TYPE_VIS_ONLY hash : public __enum_hash<_Tp>
+{
+};
#endif
Modified: libcxx/trunk/test/std/utilities/function.objects/unord.hash/enum.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/unord.hash/enum.pass.cpp?rev=278300&r1=278299&r2=278300&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/unord.hash/enum.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/function.objects/unord.hash/enum.pass.cpp Wed Aug 10 17:45:26 2016
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11
+
// <functional>
// make sure that we can hash enumeration values
@@ -14,8 +16,6 @@
#include "test_macros.h"
-#if TEST_STD_VER >= 14
-
#include <functional>
#include <cassert>
#include <type_traits>
@@ -59,6 +59,3 @@ int main()
test<Fruits>();
}
-#else
-int main () {}
-#endif
Added: libcxx/trunk/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp?rev=278300&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp Wed Aug 10 17:45:26 2016
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <functional>
+
+// Hashing a struct w/o a defined hash should *not* fail, but it should
+// create a type that is not constructible and not callable.
+// See also: http://cplusplus.github.io/LWG/lwg-active.html#2543
+
+#include <functional>
+#include <cassert>
+#include <type_traits>
+
+#include "test_macros.h"
+
+struct X {};
+
+int main()
+{
+ using H = std::hash<X>;
+ static_assert(!std::is_default_constructible<H>::value, "");
+ static_assert(!std::is_copy_constructible<H>::value, "");
+ static_assert(!std::is_move_constructible<H>::value, "");
+ static_assert(!std::is_copy_assignable<H>::value, "");
+ static_assert(!std::is_move_assignable<H>::value, "");
+#if TEST_STD_VER > 14
+ static_assert(!std::is_callable<H(X&)>::value, "");
+ static_assert(!std::is_callable<H(X const&)>::value, "");
+#endif
+}
More information about the cfe-commits
mailing list