From 4b3a334cf553b9f0b7f831538cb4d23fbdb0594f Mon Sep 17 00:00:00 2001
From: johannst <johannst@users.noreply.github.com>
Date: Wed, 12 Apr 2023 20:57:45 +0000
Subject: deploy: d6deac54dd372c946942637636846893694ce521

---
 development/c++/Makefile       |  5 ++-
 development/c++/concepts-11.cc |  3 +-
 development/c++/tmpl-pair.cc   | 73 ++++++++++++++++++++++++++++++++++++++++++
 development/c++/tmpl-void_t.cc | 47 +++++++++++++++++++++++++++
 4 files changed, 125 insertions(+), 3 deletions(-)
 create mode 100644 development/c++/tmpl-pair.cc
 create mode 100644 development/c++/tmpl-void_t.cc

(limited to 'development/c++')

diff --git a/development/c++/Makefile b/development/c++/Makefile
index 610b5a2..ca752d9 100644
--- a/development/c++/Makefile
+++ b/development/c++/Makefile
@@ -1,4 +1,4 @@
-SRC = concepts-11.cc meta.cc meta2.cc meta4.cc
+SRC = concepts-11.cc meta.cc meta2.cc meta4.cc tmpl-pair.cc tmpl-void_t.cc
 BIN = $(SRC:.cc=)
 
 all: $(BIN)
@@ -6,5 +6,8 @@ all: $(BIN)
 %: %.cc
 	$(CXX) -o $* $^ -std=c++17 -g -fsanitize=address -fsanitize=undefined -fsanitize=leak
 
+fmt:
+	clang-format -i $(SRC)
+
 clean:
 	$(RM) $(BIN)
diff --git a/development/c++/concepts-11.cc b/development/c++/concepts-11.cc
index 888ff4d..cec8716 100644
--- a/development/c++/concepts-11.cc
+++ b/development/c++/concepts-11.cc
@@ -32,8 +32,7 @@ struct is_entry {
     template<typename TT>
     using val = decltype(std::declval<TT>().val());
 
-    static constexpr bool value = is_valid_v<T, init> &&
-                                  is_valid_with_ret_v<T, int, tag> &&
+    static constexpr bool value = is_valid_v<T, init> && is_valid_with_ret_v<T, int, tag> &&
                                   is_valid_with_ret_v<T, typename T::Type, val>;
 };
 
diff --git a/development/c++/tmpl-pair.cc b/development/c++/tmpl-pair.cc
new file mode 100644
index 0000000..a8acaed
--- /dev/null
+++ b/development/c++/tmpl-pair.cc
@@ -0,0 +1,73 @@
+// Copyright (C) 2023 johannst
+
+enum Kind {
+    kPrimary,
+    kTT,
+    kIntBool,
+    kIntInt,
+};
+
+// (1) Primary template.
+template<typename T, typename U = bool>
+struct pair {
+    static constexpr Kind kind = kPrimary;
+};
+
+// (2) Partial template specialization.
+template<typename T>
+struct pair<T, T> {
+    static constexpr Kind kind = kTT;
+};
+
+// (3) Template specialization.
+template<>
+struct pair<int, bool> {
+    static constexpr Kind kind = kIntBool;
+};
+
+// (4) Template specialization.
+template<>
+struct pair<int, int> {
+    static constexpr Kind kind = kIntInt;
+};
+
+int main() {
+    static_assert(pair<int>::kind == kIntBool, "");
+    // * Compare template arg list with primary template, we only supplied one
+    //   arg, the second one will be defaulted as
+    //   pair<int, bool>
+    // * Compare template arg list against available specializations, this will
+    //   try to match the pattern <int, bool> against the patterns defined in the
+    //   partial specializations.
+    // * (2) <int, bool> pattern does not match
+    // * (3) <int, bool> pattern does match
+    // * (4) <int, bool> pattern does not match
+    // * Pick the most specialized version -> (3)
+
+    static_assert(pair<char, char>::kind == kTT, "");
+    // * Compare template arg list against available specializations, this will
+    //   try to match the pattern <char, char> against the patterns defined in the
+    //   partial specializations.
+    // * (2) <char, char> pattern does match
+    // * (3) <char, char> pattern does not match
+    // * (4) <char, char> pattern does not match
+    // * Pick the most specialized version -> (2)
+
+    static_assert(pair<int, int>::kind == kIntInt, "");
+    // * Compare template arg list against available specializations, this will
+    //   try to match the pattern <int, int> against the patterns defined in the
+    //   partial specializations.
+    // * (2) <int, int> pattern does match
+    // * (3) <int, int> pattern does match
+    // * (4) <int, int> pattern does not match
+    // * Pick the most specialized version -> (3)
+
+    static_assert(pair<char, short>::kind == kPrimary, "");
+    // * Compare template arg list against available specializations, this will
+    //   try to match the pattern <char, short> against the patterns defined in the
+    //   partial specializations.
+    // * (2) <char, short> pattern does not match
+    // * (3) <char, short> pattern does not match
+    // * (4) <char, short> pattern does not match
+    // * No specialization matches, take the primary template.
+}
diff --git a/development/c++/tmpl-void_t.cc b/development/c++/tmpl-void_t.cc
new file mode 100644
index 0000000..fd95315
--- /dev/null
+++ b/development/c++/tmpl-void_t.cc
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 johannst
+
+#include <type_traits>
+
+// (1) Primary template.
+template<typename T, typename = void>
+struct is_valid : std::false_type {};
+
+// (2) Partial template specialization.
+template<typename T>
+struct is_valid<T, std::void_t<decltype(std::declval<T>().some_fun1()),
+                               decltype(std::declval<T>().some_fun2())>> : std::true_type {};
+struct A {
+    void some_fun1() {}
+    void some_fun2() {}
+};
+
+struct B {};
+
+static_assert(is_valid<A>::value, "is true");
+// * Compare template arg list with primary template, we only supplied one
+//   arg, the second one will be defaulted as
+//   is_valid<A, void>
+// * Compare template arg list against available specializations, this will
+//   try to match the pattern <A, void> against the patterns defined in the
+//   partial specializations.
+// * Try specialization (2)
+//   * T -> A
+//   * Evaluate std::void_t -> decltype's are well-formed
+//     std::void_t<...> -> void
+//   * Specialization (2) matches <A, void>
+// * Pick the most specialized version -> (2)
+
+static_assert(!is_valid<B>::value, "is false");
+// * Compare template arg list with primary template, we only supplied one
+//   arg, the second one will be defaulted as
+//   is_valid<A, void>
+// * Compare template arg list against available specializations, this will
+//   try to match the pattern <B, void> against the patterns defined in the
+//   partial specializations.
+// * Try specialization (2)
+//   * T -> B
+//   * Evaluate std::void_t -> decltype's are ill-formed
+//   * Specialization (2) is removed from candidate set, no hard error (SFINAE)
+// * No specialization matches, take the primary template.
+
+int main() {}
-- 
cgit v1.2.3