hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/tutorial/06_functions.sfinae
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-19 22:04:44 +0200
committerhachem <im@hachem.wtf>2026-09-19 22:04:44 +0200
commit2da2c56c72e7085bd9a52f848df90c6fc701de7f (patch)
tree96cf837a606297aed921b9adaac783940a1aa7cd /tutorial/06_functions.sfinae
parent6487b5b5301f6cb37c95c3571578d5a42adb2a1a (diff)
docs: add tutorial
Diffstat (limited to 'tutorial/06_functions.sfinae')
-rw-r--r--tutorial/06_functions.sfinae118
1 files changed, 118 insertions, 0 deletions
diff --git a/tutorial/06_functions.sfinae b/tutorial/06_functions.sfinae
new file mode 100644
index 0000000..a85e5fa
--- /dev/null
+++ b/tutorial/06_functions.sfinae
@@ -0,0 +1,118 @@
+// lesson 6: functions
+//
+// ::define<NAME, ::parameters<NAME, ...>, ::sequence<...>> defines a function
+// a function sees nothing but its parameters. it gives back a type with
+// ::return<TYPE>, or ::void if it never does. calling it is a type too:
+// ::invoke_result_t<NAME, ::arguments<TYPE, ...>>, and every argument must be
+// a ::decltype so it carries a value
+
+::define<
+ ::name<'s', 'q', 'u', 'a', 'r', 'e'>,
+ ::parameters<::name<'x'>>,
+ ::sequence<
+ ::return<
+ ::decltype(
+ ::product<
+ ::value_of<::name<'x'>>,
+ ::value_of<::name<'x'>>
+ >
+ )
+ >::commit
+ >
+>::commit;
+
+// prints 25
+
+::emit<
+ ::invoke_result_t<
+ ::name<'s', 'q', 'u', 'a', 'r', 'e'>,
+ ::arguments<::decltype(::difference<'F', 'A'>)>
+ >
+>::commit;
+
+// a function can return anything a type can be, which includes a tuple of
+// characters, which is the closest thing to a string you will get
+
+::define<
+ ::name<'g', 'r', 'e', 'e', 't'>,
+ ::parameters<>,
+ ::sequence<
+ ::return<
+ ::tuple<
+ ::integral_constant<::char, ::difference<'h', '\0'>>,
+ ::integral_constant<::char, ::difference<'e', '\0'>>,
+ ::integral_constant<::char, ::difference<'y', '\0'>>
+ >
+ >::commit
+ >
+>::commit;
+
+::emit<
+ ::invoke_result_t<
+ ::name<'g', 'r', 'e', 'e', 't'>,
+ ::arguments<>
+ >
+>::commit;
+
+// the result is a type. to use it as a value in arithmetic, ::declval<T>() gets
+// the value back out. the parentheses are mandatory. it is a function, after all
+// this prints 10
+
+::emit<
+ ::decltype(
+ ::sum<
+ ::declval<
+ ::invoke_result_t<
+ ::name<'s', 'q', 'u', 'a', 'r', 'e'>,
+ ::arguments<::decltype(::difference<'D', 'A'>)>
+ >
+ >(),
+ ::difference<'B', 'A'>
+ >
+ )
+>::commit;
+
+// recursion works, because nothing stopped it. factorial of 5
+
+::define<
+ ::name<'f', 'a', 'c', 't'>,
+ ::parameters<::name<'n'>>,
+ ::sequence<
+ ::enable_if_t<
+ ::less<
+ ::value_of<::name<'n'>>,
+ ::difference<'B', 'A'>
+ >::value,
+ ::sequence<
+ ::return<::decltype(::difference<'B', 'A'>)>::commit
+ >
+ >::commit,
+ ::return<
+ ::decltype(
+ ::product<
+ ::value_of<::name<'n'>>,
+ ::declval<
+ ::invoke_result_t<
+ ::name<'f', 'a', 'c', 't'>,
+ ::arguments<
+ ::decltype(
+ ::sum<
+ ::value_of<::name<'n'>>,
+ ::difference<'A', 'B'>
+ >
+ )
+ >
+ >
+ >()
+ >
+ )
+ >::commit
+ >
+>::commit;
+
+::emit<
+ ::invoke_result_t<
+ ::name<'f', 'a', 'c', 't'>,
+ ::arguments<::decltype(::difference<'F', 'A'>)>
+ >
+>::commit;