diff mbox series

PR libstdc++/83607 specialize Boyer-Moore searchers for std::byte

Message ID 20180104102540.GA24279@redhat.com
State New
Headers show
Series PR libstdc++/83607 specialize Boyer-Moore searchers for std::byte | expand

Commit Message

Jonathan Wakely Jan. 4, 2018, 10:25 a.m. UTC
This makes the searchers use the same optimization for std::byte as
for narrow character types, and also uses it when the predicate is
std::equal_to<C> rather than the default std::equal_to<void>.

I wanted to call the new trait __is_byte_size, for pun value, but it
isn't true for everything with size 1, because user-defined
enumeration types could have weird equality semantics that would mean
the optimization isn't valid.

	PR libstdc++/83607
	* include/std/functional (__is_byte_like): New trait.
	(__is_std_equal_to): Remove.
	(__boyer_moore_base_t): Use __is_byte_like instead of
	__is_std_equal_to.
	* include/experimental/functional (__is_std_equal_to): Remove.
	(__boyer_moore_base_t): Use __is_byte_like instead of
	__is_std_equal_to.
	* testsuite/20_util/function_objects/83607.cc: New test.

Tested powerpc64le-linux, committed to trunk.
commit b5b64a9c9aa61dde20491b57e270684fe8fb6c67
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jan 3 13:54:11 2018 +0000

    PR libstdc++/83607 specialize Boyer-Moore searchers for std::byte
    
            PR libstdc++/83607
            * include/std/functional (__is_byte_like): New trait.
            (__is_std_equal_to): Remove.
            (__boyer_moore_base_t): Use __is_byte_like instead of
            __is_std_equal_to.
            * include/experimental/functional (__is_std_equal_to): Remove.
            (__boyer_moore_base_t): Use __is_byte_like instead of
            __is_std_equal_to.
            * testsuite/20_util/function_objects/83607.cc: New test.
diff mbox series

Patch

diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 950f89cfc31..de68c802661 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -157,20 +157,13 @@  inline namespace fundamentals_v1
       std::tuple<_GLIBCXX_STD_C::array<_Tp, _Len>, _Pred> _M_bad_char;
     };
 
-  template<typename _Pred>
-    struct __is_std_equal_to : std::false_type { };
-
-  template<>
-    struct __is_std_equal_to<std::equal_to<void>> : std::true_type { };
-
   // Use __boyer_moore_array_base when pattern consists of narrow characters
-  // and uses std::equal_to as the predicate.
+  // (or std::byte) and uses std::equal_to as the predicate.
   template<typename _RAIter, typename _Hash, typename _Pred,
            typename _Val = typename iterator_traits<_RAIter>::value_type,
 	   typename _Diff = typename iterator_traits<_RAIter>::difference_type>
     using __boyer_moore_base_t
-      = std::conditional_t<sizeof(_Val) == 1 && is_integral<_Val>::value
-			   && __is_std_equal_to<_Pred>::value,
+      = std::conditional_t<std::__is_byte_like<_Val, _Pred>::value,
 			   __boyer_moore_array_base<_Diff, 256, _Pred>,
 			   __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
 
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 1175deb6597..2b46ba899dd 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -879,7 +879,29 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _Fn _M_fn;
     };
 
-#if __cplusplus > 201402L
+  template<typename _Tp, typename _Pred>
+    struct __is_byte_like : false_type { };
+
+  template<typename _Tp>
+    struct __is_byte_like<_Tp, equal_to<_Tp>>
+    : __bool_constant<sizeof(_Tp) == 1 && is_integral<_Tp>::value> { };
+
+  template<typename _Tp>
+    struct __is_byte_like<_Tp, equal_to<void>>
+    : __bool_constant<sizeof(_Tp) == 1 && is_integral<_Tp>::value> { };
+
+#if __cplusplus >= 201703L
+  // Declare std::byte (full definition is in <cstddef>).
+  enum class byte : unsigned char;
+
+  template<>
+    struct __is_byte_like<byte, equal_to<byte>>
+    : true_type { };
+
+  template<>
+    struct __is_byte_like<byte, equal_to<void>>
+    : true_type { };
+
 #define __cpp_lib_not_fn 201603
   /// [func.not_fn] Function template not_fn
   template<typename _Fn>
@@ -988,20 +1010,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       tuple<_GLIBCXX_STD_C::array<_Tp, _Len>, _Pred> _M_bad_char;
     };
 
-  template<typename _Pred>
-    struct __is_std_equal_to : false_type { };
-
-  template<>
-    struct __is_std_equal_to<equal_to<void>> : true_type { };
-
   // Use __boyer_moore_array_base when pattern consists of narrow characters
-  // and uses std::equal_to as the predicate.
+  // (or std::byte) and uses std::equal_to as the predicate.
   template<typename _RAIter, typename _Hash, typename _Pred,
            typename _Val = typename iterator_traits<_RAIter>::value_type,
 	   typename _Diff = typename iterator_traits<_RAIter>::difference_type>
     using __boyer_moore_base_t
-      = conditional_t<sizeof(_Val) == 1 && is_integral<_Val>::value
-		      && __is_std_equal_to<_Pred>::value,
+      = conditional_t<__is_byte_like<_Val, _Pred>::value,
 		      __boyer_moore_array_base<_Diff, 256, _Pred>,
 		      __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
 
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/83607.cc b/libstdc++-v3/testsuite/20_util/function_objects/83607.cc
new file mode 100644
index 00000000000..a752ca759a8
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_objects/83607.cc
@@ -0,0 +1,61 @@ 
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <functional>
+#include <cstddef>
+
+// PR libstdc++/83607
+
+using std::boyer_moore_searcher;
+using std::boyer_moore_horspool_searcher;
+using std::byte;
+using std::hash;
+using std::equal_to;
+
+void
+test01()
+{
+  constexpr auto expected = sizeof(boyer_moore_searcher<const char*>);
+  static_assert(sizeof(boyer_moore_searcher<const long*>) != expected);
+  using T1 = boyer_moore_searcher<char*, hash<char>, equal_to<char>>;
+  static_assert(sizeof(T1) == expected);
+  using T2 = boyer_moore_searcher<byte*>;
+  static_assert(sizeof(T2) == expected);
+  using T3 = boyer_moore_searcher<const byte*>;
+  static_assert(sizeof(T3) == expected);
+  using T4 = boyer_moore_searcher<const byte*, hash<byte>, equal_to<byte>>;
+  static_assert(sizeof(T4) == expected);
+}
+
+void
+test02()
+{
+  constexpr auto expected = sizeof(boyer_moore_horspool_searcher<const char*>);
+  static_assert(sizeof(boyer_moore_horspool_searcher<const long*>) != expected);
+  using T1 = boyer_moore_horspool_searcher<char*, hash<char>, equal_to<char>>;
+  static_assert(sizeof(T1) == expected);
+  using T2 = boyer_moore_horspool_searcher<byte*>;
+  static_assert(sizeof(T2) == expected);
+  using T3 = boyer_moore_horspool_searcher<const byte*>;
+  static_assert(sizeof(T3) == expected);
+  using T4
+    = boyer_moore_horspool_searcher<const byte*, hash<byte>, equal_to<byte>>;
+  static_assert(sizeof(T4) == expected);
+}