diff options
| author | hachem <im@hachem.wtf> | 2026-09-19 22:04:44 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-19 22:04:44 +0200 |
| commit | 2da2c56c72e7085bd9a52f848df90c6fc701de7f (patch) | |
| tree | 96cf837a606297aed921b9adaac783940a1aa7cd /tutorial/06_functions.sfinae | |
| parent | 6487b5b5301f6cb37c95c3571578d5a42adb2a1a (diff) | |
docs: add tutorial
Diffstat (limited to 'tutorial/06_functions.sfinae')
| -rw-r--r-- | tutorial/06_functions.sfinae | 118 |
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; |
