метафункция - это шаблонная структура, которая содержит тип или значение
template <auto Value>
struct value_identity {
static constexpr value = Value;
using type = decltype(value);
};
...
auto x = value_identity<239>::value;
template <typename T>
constexpr auto value = value_identity<T>::value;
template <typename T>
using value_identity_t = value_identity<T>::typestd::conjunction, std::disjunction, std::negation - метафункции над типами, которые сами по себе метафункции. нужны, когда мы хотим проверить несколько условий про тип
SFINAE = subtitution failure is not an error
если в момент инстанцирования объявления функции (когда шаблон пытается подставить тип в объявление функции) получается некорректный тип, то это не ошибка компиляции, а компилятор просто не будет рассматривать эту версию перегрузку. рассматривается следующий кандидат на перегрузку
выведется 1, 2
первая версия предпочтительнее, но при подстановке в объявление функции int, получился невалидный тип, поэтому та версия перегрузки откидывается
SFINAE работает только в объявлении. тело функции истанцируется уже после того, как выбрана версия перегрузки
как сделать так, чтобы при вызове от integral type выбиралась одна версия перегрузки, а для всех остальных другая?
std::enable_if - если получает true первым аргументом, то, имеет внутри себя алиас на второй аргумент. если false, то это пустая структура и std::enable_if_t будет невалидный тип и вся функция с std::enable_if_t выкинется из кандидатов

auto f(T x) -> decltype(x%2) - для типов, у которых определен оператор %
шаблонные функции, как и обычные, не могут отличаться в сигнатуре лишь параметром по умолчанию
поэтому здесь - redefinition (возникает на ранней стадии компиляции, до подстановки типа в шаблон)
хотя если добавить ещё шаблонный аргумент по умолчанию, то сработает
чтобы повлиять на выбор перегрузки шаблонной функции, мы должны передать в неё аргумент вида std::enable_if<constexpr condition, bool> и сделать его по умолчанию = true/false (не важно) если условие выполняется, то будет bool = true а если нет, то будет невалидный тип = true -> эта версия перегрузки не выберется
если сделать несколько функций с не взаимоисключающими параметрами (в одной enable_if<is_integral>, в другой enable_if<is_bool>), то будет CE - ambigous call
std::conjunction implementation

не конченная реализация:
template <typename...>
struct conjunction : std::true_type {};
template <typename B1, typename... Bn>
struct conjunction<B1, Bn...> : std::conditional_t<B1::value
, conjunction<Bn...> //if true check more
, B1 //if false
> {};is_class implementation
пытаемся понять тип, от которого наследуемся. для этого нужно знать возвращаемый тип функции test с шаблонным параметром T от nullptr. выбираем сигнатуру функции
наследуется от true_type, если у этого типа могут быть указатели на члены, они существуют только у классовых типов и не важно есть ли на самом деле там такой член типа int, тип сам по себе корректный
наследуется от false_type во всех других случаях
is_pointer implementation
перегрузка функции по T и T*
перегрузка по T и T* с помощью requirement’а

is_polymorphic implementation
наследуемся от результата функции. выбираем сигнатуру функции
первый кандидат: кастим nullptr к T* - всегда возможно. делаем dynamic_cast от T* к void*. такое dynamic_cast может делать только от полиморфных типов. значит если тип не полиморфный, то кандидат отбрасывается
(кастим к const volatile тк если у нас изначально были cv-квалификаторы, то мы не можем их просто отбросить, а навесить - запросто)
has_method_construct implementation
comma trick - засчёт оператора запятая тип выражения всегда такой, какой нужно, но само выражение корректно или некорректно в зависимости от сущестовования метода construct
как реализована std::declval<T>?
template <typename T> std::add_rvalue_reference
не имеет определения. нужна только для метапрограммирования и юзается почти всегда под decltype. в любом случае вычисляется в compile time. если попытаться вызваться в контексте runtime вычислений, то будет ошибка линкера
T&& потому что если T - imcomplete type, то возвращение объекта imcomplete type даже в unevaluated context - CE крч чтоб вернуть T из функции, компилятору нужно знать определение T. навесив && мы можем использовать declval даже с типами без определений
is_copy_constructible implementation

is_constructible & is_copy_constructible & is_move_constructible implementation

is no_throw_move_constructible implementation
is_nothrow_move_constructible implementation
v2:

std::is_convertible
разница между std::is_constructible и std::is_convertible в том, что первое не проверяет implicit convertions
создаём ссылку на функцию, которая принимает To по значению и возвращает войд и в эту функцию пытаемся отдать From и проверяем корректно ли
std::common_type
принимает типы и возвращает общий для них тип. общий тип - такой, что все типы к нему приводятся как по двум данным типам получить общий? - результат тернарного оператора будет общим для них типом однако тернарный оператор не сможет найти общего родителя, если он не присутствовал среди типов также и std::common_type не найдёт общего родителя + важно в каком порядке передавать “сына”, “дочь” и “маму”, ведь на комбинации “мама, сын, дочь” будет CE
std::type_identity<T> - структура, в которой написано using type = T;
такая реализация common_type - не SFINAE-friendly, тк даже если common type’а нету, он всё равно проистанцирует шаблонную структуру, попытается вычистить тернарный оператор и упадёт
c С++11 она стала SFINAE-friendly
SFINAE-friendliness
если функция не SFINAE-friendly, то её нельзя использовать в контексте SFINAE функция не SFINAE-friendly, если чтобы понять её тип, нужно истанцировать её тело. при инстанцировании может возникнуть CE
void() тк нужен экспрешен. крч это void созданный по умолчанию. если бы было просто void, то была бы синтаксическая ошибка, тк под decltype должен быть экспрешен
некоторые type_traits нельзя реализовать стандартными средствами языка, например std::is_standart_layout, std::is_abstract, std::is_aggregate, они зашиты в компилятор
проверить, что тип T есть в пакете Ts
или

поиск корня числа за логарифм в compile-time

перевод двоичного числа в десятичное в compile-time:
чутка ублюдошная хуйня
