#include <iostream>
#include <type_traits>
#include <tuple>
template<typename T>
struct TypeInfo {
static constexpr bool is_pointer = std::is_pointer_v<T>;
static constexpr bool is_reference = std::is_reference_v<T>;
static constexpr bool is_const = std::is_const_v<std::remove_reference_t<T>>;
static constexpr size_t size = sizeof(T);
using remove_pointer = std::remove_pointer_t<T>;
using remove_reference = std::remove_reference_t<T>;
using remove_const = std::remove_const_t<std::remove_reference_t<T>>;
};
template<typename... Ts>
struct TypeList {
static constexpr size_t size = sizeof...(Ts);
template<template<typename> typename F>
using transform = TypeList<F<Ts>...>;
template<typename T>
using append = TypeList<Ts..., T>;
template<typename T>
using prepend = TypeList<T, Ts...>;
};
template<typename T>
struct is_container : std::false_type {};
template<typename T, typename Alloc>
struct is_container<std::vector<T, Alloc>> : std::true_type {};
template<typename T, typename Alloc>
struct is_container<std::list<T, Alloc>> : std::true_type {};
template<typename T>
inline constexpr bool is_container_v = is_container<T>::value;
template<typename T>
void process_if_container(T&& value) {
if constexpr (is_container_v<std::decay_t<T>>) {
std::cout << "Processing container of size: " << value.size() << "\n";
} else {
std::cout << "Not a container\n";
}
}
template<int N>
struct Factorial {
static constexpr int value = N * Factorial<N - 1>::value;
};
template<>
struct Factorial<0> {
static constexpr int value = 1;
};
template<int N>
constexpr int factorial_v = Factorial<N>::value;
template<size_t N>
struct Fibonacci {
static constexpr size_t value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value;
};
template<>
struct Fibonacci<0> {
static constexpr size_t value = 0;
};
template<>
struct Fibonacci<1> {
static constexpr size_t value = 1;
};
template<size_t N>
constexpr size_t fibonacci_v = Fibonacci<N>::value;
template<typename... Args>
constexpr size_t count_args = sizeof...(Args);
template<typename... Args>
constexpr bool all_same_types() {
return (std::is_same_v<Args, std::tuple_element_t<0, std::tuple<Args...>>> && ...);
}
template<typename... Args>
constexpr auto sum_args(Args... args) {
return (args + ...);
}
template<typename F, typename... Args>
decltype(auto) invoke(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
template<typename T>
class Singleton {
public:
static T& instance() {
static T instance;
return instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
protected:
Singleton() = default;
};
class Logger : public Singleton<Logger> {
friend class Singleton<Logger>;
public:
void log(const std::string& msg) {
std::cout << "[LOG] " << msg << "\n";
}
};
template<typename Derived>
class Cloneable {
public:
virtual ~Cloneable() = default;
std::unique_ptr<Derived> clone() const {
return std::unique_ptr<Derived>(static_cast<Derived*>(clone_impl()));
}
protected:
virtual Cloneable* clone_impl() const = 0;
};
class Document : public Cloneable<Document> {
std::string content;
public:
explicit Document(std::string c) : content(std::move(c)) {}
Document* clone_impl() const override {
return new Document(content);
}
void print() const {
std::cout << "Document: " << content << "\n";
}
};
template<auto Value>
struct IntegralConstant {
static constexpr auto value = Value;
};
template<size_t Index, typename... Types>
struct TypeAt;
template<typename First, typename... Rest>
struct TypeAt<0, First, Rest...> {
using type = First;
};
template<size_t Index, typename First, typename... Rest>
struct TypeAt<Index, First, Rest...> {
using type = typename TypeAt<Index - 1, Rest...>::type;
};
template<size_t Index, typename... Types>
using type_at_t = typename TypeAt<Index, Types...>::type;
template<typename... Types>
struct TypeCounter {
template<typename T>
static constexpr size_t count() {
return ((std::is_same_v<T, Types> ? 1 : 0) + ...);
}
};
template<typename T, typename... Args>
constexpr bool is_one_of = (std::is_same_v<T, Args> || ...);
template<typename T>
concept Arithmetic = std::is_arithmetic_v<T>;
template<typename T>
concept Container = requires(T t) {
{ t.begin() } -> std::input_or_output_iterator;
{ t.end() } -> std::input_or_output_iterator;
{ t.size() } -> std::convertible_to<size_t>;
};
template<Arithmetic T>
T add(T a, T b) {
return a + b;
}
template<Container C>
auto sum_container(const C& container) -> typename C::value_type {
typename C::value_type sum{};
for (const auto& item : container) {
sum += item;
}
return sum;
}
int main() {
static_assert(factorial_v<5> == 120);
static_assert(fibonacci_v<10> == 55);
std::cout << "Factorial<5>: " << factorial_v<5> << "\n";
std::cout << "Fibonacci<10>: " << fibonacci_v<10> << "\n";
std::vector<int> vec = {1, 2, 3, 4, 5};
process_if_container(vec);
process_if_container(42);
Logger::instance().log("Hello from singleton");
auto doc = std::make_unique<Document>("Original");
auto copy = doc->clone();
copy->print();
std::cout << "Sum: " << sum_args(1, 2, 3, 4, 5) << "\n";
return 0;
}