# sfinae Substitution Failure Is Not An Error. everything else is. a toy language which takes' C++ template metaprogramming to another level. ## build make release build, ./sfinae in the root, objects in bin/ make debug rebuild with address and undefined sanitizers make check run every program in examples/ and tutorial/ make format clang-format the sources make lint clang-tidy naming check make clean make install copy ./sfinae to PREFIX/bin, PREFIX defaults to /usr/local make uninstall ## run ./sfinae examples/hello.sfinae ## learning it six lessons under tutorial/, each a program that runs and explains itself in its comments. read them in order: 01_hello.sfinae there are no strings, a string is a tuple of characters 02_numbers.sfinae there are no numbers, a number is the distance between two characters 03_variables.sfinae a variable holds a type, and there is no assignment 04_conditions.sfinae nothing is a condition until you say ::value 05_loops.sfinae ::repeat, and counting with the undeclare dance 06_functions.sfinae functions take types, return types, and see only their parameters examples/ has more, including fib(0) to fib(10). ## the rules - every notion starts with `::` and every statement ends with `::commit;`. nothing happens until it is committed - there are no numeric literals. a digit is a lexer error. the only way to get a number is to subtract two characters: `::difference<'F', 'A'>` is 5 - there are no strings. a string is a `::tuple` of `::integral_constant<::char, N>` types, one per character, each its own distance from `'\0'` - names are lists of characters: `::name<'f', 'i', 'b'>`, at most 15 of them - a variable holds a type, and the type must be a `::decltype(...)` of a value or it cannot be declared - reassignment does not exist. `::undeclare` it, then `::declare` it again - conditions are not conditions until you say `::value` - loop, if and function bodies are a `::sequence<...>` of committed statements, separated by commas - functions take types, return types, and see nothing but their parameters - comments are `//` to the end of the line ## statements ::declare::commit; ::undeclare::commit; ::emit::commit; prints what the type says, then a newline ::repeat::commit; ::enable_if_t::commit; ::static_assert::commit; fails at runtime ::define, SEQUENCE>::commit; ::return::commit; only inside a function ## types ::void ::int32_t ::byte ::size_t ::char ::remove_cv_t does nothing ::array an array type with an extent ::conditional_t ::decltype(VALUE) the only type that carries a value ::integral_constant<::char, VALUE> a character ::tuple says what its elements say, in order ::invoke_result_t> a call ## values ::difference<'c', 'c'> the one and only literal ::sum ::product ::quotient ::value_of ::extent::value an array's extent, 0 otherwise ::tuple_size::value same thing, longer ::integral_constant<::size_t, V>::value also does nothing ::conditional ::declval() the value inside a decltype ## conditions ::true_type::value ::false_type::value ::is_same::value ::equal::value ::less::value ## what emit prints ::decltype(V) the number ::integral_constant<::char, V> the character ::tuple<...> its elements, glued together ::array array[N] ::void nothing, not even a newline anything else the type's name ## license MIT, see LICENSE.