template<typename T>
struct has_iterator {
    template<typename U>
    static auto test(int) -> decltype(std::begin(std::declval<U&>()), std::end(std::declval<U&>()), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
constexpr bool has_iterator_v = has_iterator<T>::value;

template<typename T>
struct has_size {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().size(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
auto serialize(T&& t) -> std::enable_if_t<has_iterator_v<std::decay_t<T>>, void> {
    for (auto&& elem : t) { serialize(elem); }
}

template<typename T>
auto serialize(T&& t) -> std::enable_if_t<!has_iterator_v<std::decay_t<T>>, void> {
    write(std::forward<T>(t));
}

template<typename T>
struct is_callable {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>()(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename F, typename... Args>
auto invoke_if_callable(F&& f, Args&&... args) -> std::enable_if_t<is_callable<F>::value, decltype(f())> {
    return std::forward<F>(f)();
}

template<typename F, typename... Args>
auto invoke_if_callable(F&& f, Args&&... args) -> std::enable_if_t<!is_callable<F>::value, void> {
    std::forward<F>(f)(std::forward<Args>(args)...);
}

template<typename T>
struct has_value_type {
    template<typename U>
    static auto test(int) -> decltype(typename U::value_type{}, std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container>
auto get_first(Container&& c) -> std::enable_if_t<has_iterator_v<Container>, decltype(*std::begin(c))> {
    return *std::begin(c);
}

template<typename T>
struct is_container {
    static constexpr bool value = has_iterator_v<T> && has_size_v<T>;
};

template<typename T>
using enable_if_container = std::enable_if_t<is_container<T>::value, int>;

template<typename T>
struct has_push_back {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().push_back(std::declval<typename U::value_type>()), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
struct has_emplace_back {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container, typename Value>
auto add_element(Container& c, Value&& v) -> std::enable_if_t<has_emplace_back<Container>::value, void> {
    c.emplace_back(std::forward<Value>(v));
}

template<typename Container, typename Value>
auto add_element(Container& c, Value&& v) -> std::enable_if_t<has_push_back<Container>::value && !has_emplace_back<Container>::value, void> {
    c.push_back(std::forward<Value>(v));
}

template<typename T>
struct is_arithmetic {
    static constexpr bool value = std::is_arithmetic_v<T>;
};

template<typename T>
struct has_operator_plus {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>() + std::declval<U>(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
auto add(T&& a, T&& b) -> std::enable_if_t<has_operator_plus<std::decay_t<T>>::value, decltype(a + b)> {
    return std::forward<T>(a) + std::forward<T>(b);
}

template<typename T>
struct has_reserve {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().reserve(0), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container>
auto optimize_capacity(Container& c, size_t n) -> std::enable_if_t<has_reserve<Container>::value, void> {
    c.reserve(n);
}

template<typename Container>
auto optimize_capacity(Container& c, size_t n) -> std::enable_if_t<!has_reserve<Container>::value, void> {}

template<typename...> using void_t = void;

template<typename T, typename = void>
struct is_iterable : std::false_type {};

template<typename T>
struct is_iterable<T, void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>> : std::true_type {};

template<typename T>
constexpr bool is_iterable_v = is_iterable<T>::value;

template<typename T>
auto process_iterable(T&& t) -> std::enable_if_t<is_iterable_v<T>, void> {
    for (const auto& item : t) { process(item); }
}

template<typename T>
auto process_iterable(T&& t) -> std::enable_if_t<!is_iterable_v<T>, void> {
    process_single(std::forward<T>(t));
}
template<typename T>
struct has_iterator {
    template<typename U>
    static auto test(int) -> decltype(std::begin(std::declval<U&>()), std::end(std::declval<U&>()), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
constexpr bool has_iterator_v = has_iterator<T>::value;

template<typename T>
struct has_size {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().size(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
auto serialize(T&& t) -> std::enable_if_t<has_iterator_v<std::decay_t<T>>, void> {
    for (auto&& elem : t) { serialize(elem); }
}

template<typename T>
auto serialize(T&& t) -> std::enable_if_t<!has_iterator_v<std::decay_t<T>>, void> {
    write(std::forward<T>(t));
}

template<typename T>
struct is_callable {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>()(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename F, typename... Args>
auto invoke_if_callable(F&& f, Args&&... args) -> std::enable_if_t<is_callable<F>::value, decltype(f())> {
    return std::forward<F>(f)();
}

template<typename F, typename... Args>
auto invoke_if_callable(F&& f, Args&&... args) -> std::enable_if_t<!is_callable<F>::value, void> {
    std::forward<F>(f)(std::forward<Args>(args)...);
}

template<typename T>
struct has_value_type {
    template<typename U>
    static auto test(int) -> decltype(typename U::value_type{}, std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container>
auto get_first(Container&& c) -> std::enable_if_t<has_iterator_v<Container>, decltype(*std::begin(c))> {
    return *std::begin(c);
}

template<typename T>
struct is_container {
    static constexpr bool value = has_iterator_v<T> && has_size_v<T>;
};

template<typename T>
using enable_if_container = std::enable_if_t<is_container<T>::value, int>;

template<typename T>
struct has_push_back {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().push_back(std::declval<typename U::value_type>()), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
struct has_emplace_back {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container, typename Value>
auto add_element(Container& c, Value&& v) -> std::enable_if_t<has_emplace_back<Container>::value, void> {
    c.emplace_back(std::forward<Value>(v));
}

template<typename Container, typename Value>
auto add_element(Container& c, Value&& v) -> std::enable_if_t<has_push_back<Container>::value && !has_emplace_back<Container>::value, void> {
    c.push_back(std::forward<Value>(v));
}

template<typename T>
struct is_arithmetic {
    static constexpr bool value = std::is_arithmetic_v<T>;
};

template<typename T>
struct has_operator_plus {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>() + std::declval<U>(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
auto add(T&& a, T&& b) -> std::enable_if_t<has_operator_plus<std::decay_t<T>>::value, decltype(a + b)> {
    return std::forward<T>(a) + std::forward<T>(b);
}

template<typename T>
struct has_reserve {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().reserve(0), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container>
auto optimize_capacity(Container& c, size_t n) -> std::enable_if_t<has_reserve<Container>::value, void> {
    c.reserve(n);
}

template<typename Container>
auto optimize_capacity(Container& c, size_t n) -> std::enable_if_t<!has_reserve<Container>::value, void> {}

template<typename...> using void_t = void;

template<typename T, typename = void>
struct is_iterable : std::false_type {};

template<typename T>
struct is_iterable<T, void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>> : std::true_type {};

template<typename T>
constexpr bool is_iterable_v = is_iterable<T>::value;

template<typename T>
auto process_iterable(T&& t) -> std::enable_if_t<is_iterable_v<T>, void> {
    for (const auto& item : t) { process(item); }
}

template<typename T>
auto process_iterable(T&& t) -> std::enable_if_t<!is_iterable_v<T>, void> {
    process_single(std::forward<T>(t));
}
template<typename T>
struct has_iterator {
    template<typename U>
    static auto test(int) -> decltype(std::begin(std::declval<U&>()), std::end(std::declval<U&>()), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
constexpr bool has_iterator_v = has_iterator<T>::value;

template<typename T>
struct has_size {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().size(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
auto serialize(T&& t) -> std::enable_if_t<has_iterator_v<std::decay_t<T>>, void> {
    for (auto&& elem : t) { serialize(elem); }
}

template<typename T>
auto serialize(T&& t) -> std::enable_if_t<!has_iterator_v<std::decay_t<T>>, void> {
    write(std::forward<T>(t));
}

template<typename T>
struct is_callable {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>()(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename F, typename... Args>
auto invoke_if_callable(F&& f, Args&&... args) -> std::enable_if_t<is_callable<F>::value, decltype(f())> {
    return std::forward<F>(f)();
}

template<typename F, typename... Args>
auto invoke_if_callable(F&& f, Args&&... args) -> std::enable_if_t<!is_callable<F>::value, void> {
    std::forward<F>(f)(std::forward<Args>(args)...);
}

template<typename T>
struct has_value_type {
    template<typename U>
    static auto test(int) -> decltype(typename U::value_type{}, std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container>
auto get_first(Container&& c) -> std::enable_if_t<has_iterator_v<Container>, decltype(*std::begin(c))> {
    return *std::begin(c);
}

template<typename T>
struct is_container {
    static constexpr bool value = has_iterator_v<T> && has_size_v<T>;
};

template<typename T>
using enable_if_container = std::enable_if_t<is_container<T>::value, int>;

template<typename T>
struct has_push_back {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().push_back(std::declval<typename U::value_type>()), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
struct has_emplace_back {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container, typename Value>
auto add_element(Container& c, Value&& v) -> std::enable_if_t<has_emplace_back<Container>::value, void> {
    c.emplace_back(std::forward<Value>(v));
}

template<typename Container, typename Value>
auto add_element(Container& c, Value&& v) -> std::enable_if_t<has_push_back<Container>::value && !has_emplace_back<Container>::value, void> {
    c.push_back(std::forward<Value>(v));
}

template<typename T>
struct is_arithmetic {
    static constexpr bool value = std::is_arithmetic_v<T>;
};

template<typename T>
struct has_operator_plus {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>() + std::declval<U>(), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename T>
auto add(T&& a, T&& b) -> std::enable_if_t<has_operator_plus<std::decay_t<T>>::value, decltype(a + b)> {
    return std::forward<T>(a) + std::forward<T>(b);
}

template<typename T>
struct has_reserve {
    template<typename U>
    static auto test(int) -> decltype(std::declval<U>().reserve(0), std::true_type{});
    template<typename>
    static std::false_type test(...);
    using type = decltype(test<T>(0));
    static constexpr bool value = type::value;
};

template<typename Container>
auto optimize_capacity(Container& c, size_t n) -> std::enable_if_t<has_reserve<Container>::value, void> {
    c.reserve(n);
}

template<typename Container>
auto optimize_capacity(Container& c, size_t n) -> std::enable_if_t<!has_reserve<Container>::value, void> {}

template<typename...> using void_t = void;

template<typename T, typename = void>
struct is_iterable : std::false_type {};

template<typename T>
struct is_iterable<T, void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>> : std::true_type {};

template<typename T>
constexpr bool is_iterable_v = is_iterable<T>::value;

template<typename T>
auto process_iterable(T&& t) -> std::enable_if_t<is_iterable_v<T>, void> {
    for (const auto& item : t) { process(item); }
}

template<typename T>
auto process_iterable(T&& t) -> std::enable_if_t<!is_iterable_v<T>, void> {
    process_single(std::forward<T>(t));
}

SFINAE

Substitution Failure Is Not An Error