[meta] Add hb_conditional<> and hb_is_convertible()
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b5512f..fc772e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -384,7 +384,7 @@
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_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)
diff --git a/src/hb-meta.hh b/src/hb-meta.hh
index 74a4457..b2344f7 100644
--- a/src/hb-meta.hh
+++ b/src/hb-meta.hh
@@ -52,6 +52,18 @@
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 @@
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 @@
};
-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
index 0000000..a7cfef5
--- /dev/null
+++ b/src/test-meta.cc
@@ -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;
+}