ITHelpself / CPlusPlus

0 stars 0 forks source link

16. Metaprogramming #17

Open ITHelpself opened 3 years ago

ITHelpself commented 3 years ago

#include <iostream>
template <unsigned int n>
struct factorial
{
    enum
    {
        value = n * factorial<n - 1>::value
    };
};
template <>
struct factorial<0>
{
    enum
    {
        value = 1
    };
};
int main()
{
    std::cout << factorial<7>::value << std::endl; // prints "5040"
}
ITHelpself commented 3 years ago

int my_array[factorial<5>::value];
ITHelpself commented 3 years ago

#include <iostream>
#include <type_traits>
template <long long n>
struct factorial : std::integral_constant<long long, n * factorial<n - 1>::value>
{
};
template <>
struct factorial<0> : std::integral_constant<long long, 1>
{
};
int main()
{
    std::cout << factorial<7>::value << std::endl; // prints "5040"
}
ITHelpself commented 3 years ago

#include <iostream>
constexpr long long factorial(long long n)
{
    return (n == 0) ? 1 : n * factorial(n - 1);
}
int main()
{
    char test[factorial(3)];
    std::cout << factorial(7) << '\n';
}
ITHelpself commented 3 years ago

constexpr long long factorial(long long n)
{
if (n == 0)
return 1;
else
return n * factorial(n - 1);
}
ITHelpself commented 3 years ago

constexpr long long factorial(int n)
{
    long long result = 1;
    for (int i = 1; i <= n; ++i)
    {
        result *= i;
    }
    return result;
}
ITHelpself commented 3 years ago

#include <iostream>
#include <utility>
template <class T, T N, class I = std::make_integer_sequence<T, N>>
struct factorial;
template <class T, T N, T... Is>
struct factorial<T, N, std::index_sequence<T, Is...>>
{
    static constexpr T value = (static_cast<T>(1) * ... * (Is + 1));
};
int main()
{
    std::cout << factorial<int, 5>::value << std::endl;
}
ITHelpself commented 3 years ago

void print_all(std::ostream &os)
{
    // base case
}
template <class T, class... Ts>
void print_all(std::ostream &os, T const &first, Ts const &... rest)
{
    os << first;
    print_all(os, rest...);
}
ITHelpself commented 3 years ago

template <class... Ts>
void print_all(std::ostream &os, Ts const &... args)
{
    using expander = int[];
    (void)expander{0,
                   (void(os << args), 0)...};
}
ITHelpself commented 3 years ago

template <class... Ts>
void print_all(std::ostream& os, Ts const&... args) {
       ((os << args), ...);
}
ITHelpself commented 3 years ago

template <class T, class... Ts>
void print_all(std::ostream &os, T const &first, Ts const &... rest)
{
    os << first;
    if constexpr (sizeof...(rest) > 0)
    {
        // this line will only be instantiated if there are further
        // arguments. if rest... is empty, there will be no call to
        // print_all(os).
        print_all(os, rest...);
    }
}
ITHelpself commented 3 years ago

template <class T, T... Ints>
class integer_sequence;
template <std::size_t... Ints>
using index_sequence = std::integer_sequence<std::size_t, Ints...>;
ITHelpself commented 3 years ago

template <class T, T N>
using make_integer_sequence = std::integer_sequence<T, /* a sequence 0, 1, 2, ..., N-1 */ >;
template<std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
ITHelpself commented 3 years ago

namespace detail
{
    template <class F, class Tuple, std::size_t... Is>
    decltype(auto) apply_impl(F &&f, Tuple &&tpl, std::index_sequence<Is...>)
    {
        return std::forward<F>(f)(std::get<Is>(std::forward<Tuple>(tpl))...);
    }
} // namespace detail
template <class F, class Tuple>
decltype(auto) apply(F &&f, Tuple &&tpl)
{
    return detail::apply_impl(std::forward<F>(f),
                              std::forward<Tuple>(tpl),
                              std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{});
}
// this will print 3
int f(int, char, double);
auto some_args = std::make_tuple(42, 'x', 3.14);
int r = apply(f, some_args); // calls f(42, 'x', 3.14)
ITHelpself commented 3 years ago

#include <iostream>
namespace details
{
    template <class RAIter, class Distance>
    void advance(RAIter &it, Distance n, std::random_access_iterator_tag)
    {
        it += n;
    }
    template <class BidirIter, class Distance>
    void advance(BidirIter &it, Distance n, std::bidirectional_iterator_tag)
    {
        if (n > 0)
        {
            while (n--)
                ++it;
        }
        else
        {
            while (n++)
                --it;
        }
    }
    template <class InputIter, class Distance>
    void advance(InputIter &it, Distance n, std::input_iterator_tag)
    {
        while (n--)
        {
            ++it;
        }
    }
} // namespace details
template <class Iter, class Distance>
void advance(Iter &it, Distance n)
{
    details::advance(it, n,
                     typename std::iterator_traits<Iter>::iterator_category{});
}
ITHelpself commented 3 years ago

#include <functional>  // for std::hash
#include <type_traits> // for std::false_type and std::true_type
#include <utility>     // for std::declval
template <class, class = void>
struct has_hash
    : std::false_type
{
};
template <class T>
struct has_hash<T, decltype(std::hash<T>()(std::declval<T>()), void())>
    : std::true_type
{
};
ITHelpself commented 3 years ago

#include <functional> // for std::hash
#include <type_traits> // for std::false_type, std::true_type, std::void_t
#include <utility> // for std::declval
template<class, class = std::void_t<> >
struct has_hash
: std::false_type
{};
template<class T>
struct has_hash<T, std::void_t< decltype(std::hash<T>()(std::declval<T>())) > >
: std::true_type
{};
ITHelpself commented 3 years ago

template< class... > using void_t = void;
ITHelpself commented 3 years ago

template <class, class = void>
struct has_less_than
    : std::false_type
{
};
template <class T>
struct has_less_than<T, decltype(std::declval<T>() < std::declval<T>(), void())>
    : std::true_type
{
};
ITHelpself commented 3 years ago

template <class K, class V>
using hash_invariant_map = std::conditional_t<
    has_hash<K>::value,
    std::unordered_map<K, V>,
    std::map<K, V>>;
ITHelpself commented 3 years ago

template<typename T>
struct ValueOrPointer
{
typename std::conditional<(sizeof(T) > sizeof(void*)), T*, T>::type vop;
};
ITHelpself commented 3 years ago

template <typename T>
struct is_pointer_: std::false_type {};
template <typename T>
struct is_pointer_<T*>: std::true_type {};
template <typename T>
struct is_pointer: is_pointer_<typename std::remove_cv<T>::type> { }
ITHelpself commented 3 years ago

template <typename T>
constexpr bool is_pointer_v = is_pointer<T>::value;
ITHelpself commented 3 years ago

template< class T > constexpr bool is_pointer_v = is_pointer<T>::value;
template< class T > constexpr bool is_reference_v = is_reference<T>::value;
ITHelpself commented 3 years ago

template <typename T>
constexpr T calculatePower(T value, unsigned power) {
return power == 0 ? 1 : value * calculatePower(value, power-1);
}
ITHelpself commented 3 years ago

void useExample() {
constexpr int compileTimeCalculated = calculatePower(3, 3); // computes at compile time,
// as both arguments are known at compilation time
// and used for a constant expression.
int value;
std::cin >> value;
int runtimeCalculated = calculatePower(value, 3); // runtime calculated,
// because value is known only at runtime.
}
ITHelpself commented 3 years ago

#include <iostream>
#include <utility>
template <class T, T V, T N, class I = std::make_integer_sequence<T, N>>
struct power;
template <class T, T V, T N, T... Is>
struct power<T, V, N, std::integer_sequence<T, Is...>>
{
    static constexpr T value = (static_cast<T>(1) * ... * (V * static_cast<bool>(Is + 1)));
};
int main()
{
    std::cout << power<int, 4, 2>::value << std::endl;
}
ITHelpself commented 3 years ago

template <typename T1, typename T2>
auto min(const T1 &a, const T2 &b)
    -> typename std::common_type<const T1 &, const T2 &>::type
{
    return a < b ? a : b;
}
template <typename T1, typename T2, typename... Args>
auto min(const T1 &a, const T2 &b, const Args &... args)
    -> typename std::common_type<const T1 &, const T2 &, const Args &...>::type
{
    return min(min(a, b), args...);
}
auto minimum = min(4, 5.8f, 3, 1.8, 3, 1.1, 9);