From 2da2c56c72e7085bd9a52f848df90c6fc701de7f Mon Sep 17 00:00:00 2001 From: hachem Date: Sat, 19 Sep 2026 22:04:44 +0200 Subject: docs: add tutorial --- tutorial/06_functions.sfinae | 118 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 tutorial/06_functions.sfinae (limited to 'tutorial/06_functions.sfinae') 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, ::sequence<...>> defines a function +// a function sees nothing but its parameters. it gives back a type with +// ::return, or ::void if it never does. calling it is a type too: +// ::invoke_result_t>, 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() 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; -- cgit v1.3