[meta] Add hb_conditional<> and hb_is_convertible()
authorBehdad Esfahbod <behdad@behdad.org>
Thu, 9 May 2019 21:35:15 +0000 (14:35 -0700)
committerBehdad Esfahbod <behdad@behdad.org>
Thu, 9 May 2019 22:24:25 +0000 (15:24 -0700)
src/Makefile.am
src/hb-meta.hh
src/test-meta.cc [new file with mode: 0644]

index 9b5512f..fc772e0 100644 (file)
@@ -384,7 +384,7 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
 dump_use_data_CPPFLAGS = $(HBCFLAGS)
 dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
 
-COMPILED_TESTS = test-algs test-iter test-ot-tag test-unicode-ranges
+COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges
 COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
 COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
 check_PROGRAMS += $(COMPILED_TESTS)
@@ -398,6 +398,10 @@ test_iter_SOURCES = test-iter.cc hb-static.cc
 test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_iter_LDADD = $(COMPILED_TESTS_LDADD)
 
+test_meta_SOURCES = test-meta.cc hb-static.cc
+test_meta_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_meta_LDADD = $(COMPILED_TESTS_LDADD)
+
 test_ot_tag_SOURCES = hb-ot-tag.cc
 test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
index 74a4457..b2344f7 100644 (file)
@@ -52,6 +52,18 @@ typedef hb_bool_tt<true> hb_true_t;
 typedef hb_bool_tt<false> hb_false_t;
 
 
+/* Basic type SFINAE. */
+
+template <bool B, typename T = void> struct hb_enable_if {};
+template <typename T>                struct hb_enable_if<true, T> { typedef T type; };
+#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr
+/* Concepts/Requires alias: */
+#define hb_requires(Cond) hb_enable_if((Cond))
+
+template <typename T, typename T2> struct hb_is_same : hb_false_t {};
+template <typename T>              struct hb_is_same<T, T> : hb_true_t {};
+#define hb_is_same(T, T2) hb_is_same<T, T2>::value
+
 /* Function overloading SFINAE and priority. */
 
 #define HB_RETURN(Ret, E) -> hb_head_tt<Ret, decltype ((E))> { return (E); }
@@ -110,6 +122,40 @@ template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
        hb_is_reference (A) >= hb_is_reference (B))
 
 
+
+template<bool B, class T, class F>
+struct _hb_conditional { typedef T type; };
+template<class T, class F>
+struct _hb_conditional<false, T, F> { typedef F type; };
+template<bool B, class T, class F>
+using hb_conditional = typename _hb_conditional<B, T, F>::type;
+
+
+template <typename From, typename To>
+struct hb_is_convertible
+{
+  private:
+  static constexpr bool   from_void = hb_is_same (void, hb_decay<From>);
+  static constexpr bool     to_void = hb_is_same (void, hb_decay<To>  );
+  static constexpr bool either_void = from_void || to_void;
+  static constexpr bool   both_void = from_void && to_void;
+
+  static hb_true_t impl2 (hb_conditional<to_void, int, To>);
+
+  template <typename T>
+  static auto impl (hb_priority<1>) HB_AUTO_RETURN ( impl2 (hb_declval (T)) )
+  template <typename T>
+  static hb_false_t impl (hb_priority<0>);
+  public:
+  static constexpr bool value = both_void ||
+                      (!either_void &&
+                       decltype (impl<hb_conditional<from_void, int, From>> (hb_prioritize))::value);
+};
+
+
+#define hb_is_convertible(From,To) hb_is_convertible<From, To>::value
+
+
 /* std::move and std::forward */
 
 template <typename T>
@@ -162,16 +208,6 @@ struct hb_reference_wrapper<T&>
 };
 
 
-template <bool B, typename T = void> struct hb_enable_if {};
-template <typename T>                struct hb_enable_if<true, T> { typedef T type; };
-#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr
-/* Concepts/Requires alias: */
-#define hb_requires(Cond) hb_enable_if((Cond))
-
-template <typename T, typename T2> struct hb_is_same : hb_false_t {};
-template <typename T>              struct hb_is_same<T, T> : hb_true_t {};
-#define hb_is_same(T, T2) hb_is_same<T, T2>::value
-
 template <typename T> struct hb_is_signed;
 template <> struct hb_is_signed<char>                  { static constexpr bool value = CHAR_MIN < 0;   };
 template <> struct hb_is_signed<signed char>           { static constexpr bool value = true;           };
diff --git a/src/test-meta.cc b/src/test-meta.cc
new file mode 100644 (file)
index 0000000..a7cfef5
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2019  Facebook, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Facebook Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+#include "hb-meta.hh"
+
+
+int
+main (int argc, char **argv)
+{
+
+  static_assert (hb_is_convertible (void, void));
+  static_assert (hb_is_convertible (void, const void));
+  static_assert (hb_is_convertible (const void, void));
+
+  static_assert (hb_is_convertible (int,  int));
+  static_assert (hb_is_convertible (char, int));
+  static_assert (hb_is_convertible (long, int));
+
+  static_assert (hb_is_convertible (int, int));
+
+  static_assert (hb_is_convertible (const int, int));
+  static_assert (hb_is_convertible (int, const int));
+  static_assert (hb_is_convertible (const int, const int));
+
+  static_assert (hb_is_convertible (int&, int));
+  static_assert (!hb_is_convertible (int, int&));
+
+  static_assert (hb_is_convertible (int, const int&));
+  static_assert (!hb_is_convertible (const int, int&));
+  static_assert (hb_is_convertible (const int, const int&));
+  static_assert (hb_is_convertible (int&, const int));
+  static_assert (hb_is_convertible (const int&, int));
+  static_assert (hb_is_convertible (const int&, const int));
+
+  static_assert (hb_is_convertible (int&, long));
+  static_assert (!hb_is_convertible (int&, long&));
+
+  static_assert (hb_is_convertible (int *, int *));
+  static_assert (hb_is_convertible (int *, const int *));
+  static_assert (!hb_is_convertible (const int *, int *));
+  static_assert (!hb_is_convertible (int *, long *));
+  static_assert (hb_is_convertible (int *, void *));
+  static_assert (!hb_is_convertible (void *, int *));
+
+  return 0;
+}