Skip to content

Instantly share code, notes, and snippets.

@mathewmariani
Last active July 5, 2016 21:32
Show Gist options
  • Save mathewmariani/f47056531f9cbbe7be902d8b1410228e to your computer and use it in GitHub Desktop.
Save mathewmariani/f47056531f9cbbe7be902d8b1410228e to your computer and use it in GitHub Desktop.
A small meta programming header for C++11.
#pragma once
/**
* elisa: a small metaprogramming header.
* FIXME: code cleanup and comment,
*/
namespace elisa {
template<class T>
using invoke = typename T::type;
template<typename... Ts>
struct type_list {};
/**
* size_of implementation
*/
namespace {
template<typename L> struct size_of_impl;
template<template<class...> typename L, typename... Ts>
struct size_of_impl<L<Ts...>> {
using type = std::integral_constant<std::size_t, sizeof...(Ts)>;
};
}
/**
* size_of
*/
template<typename L>
using size_of = invoke<size_of_impl<L>>;
/**
* size
*/
template<typename L>
constexpr std::size_t size() {
return invoke<size_of_impl<L>>();
}
/**
* rename_impl implementation
*/
namespace {
template<typename TOld, template<class...> typename TNew> struct rename_impl;
template<template<class...> typename TOld, typename... Ts, template<class...> typename TNew>
struct rename_impl<TOld<Ts...>, TNew> {
using type = TNew<Ts...>;
};
}
/**
* rename TOld to TNew
*/
template<typename TOld, template<class...> typename TNew>
using rename = invoke<rename_impl<TOld, TNew>>;
/**
* rename to std::tuple
*/
template<template<class...> typename L, typename... Ts>
using Tuple = rename<L<Ts...>, std::tuple>;
/**
* concat_impl implementation
*/
namespace {
template<typename... L> struct concat_impl;
template<template<class...> typename L>
struct concat_impl<L<>> {
using type = L<>;
};
template<template<class...> typename L, typename... Ts>
struct concat_impl<L<Ts...>> {
using type = L<Ts...>;
};
template<template<class...> typename L1, typename... T1s,
template<class...> typename L2, typename... T2s, typename... Ts>
struct concat_impl <L1<T1s...>, L2<T2s...>, Ts...> {
using type = concat_impl<L1<T1s..., T2s...>, Ts...>;
};
}
/**
* concat L1, L2, ..., Ln
*/
template<class... L>
using concat = invoke<concat_impl<L...>>;
/**
* filter_impl implementation
*/
namespace {
template<template<class> typename, typename> struct filter_impl;
template<template<class> typename P, typename T>
struct filter_impl {
using type = type_list<>;
};
template<template<class> class P, typename T, typename... Ts>
struct filter_impl<P, type_list<T, Ts...>> {
// recursive removing the first element T
using next = filter_impl<P, type_list<Ts...>>;
using type = std::conditional_t<P<T>::value, concat<type_list<T>, next>, next>;
};
}
/**
* filter T using P
*/
template<template<class> typename P, typename T>
using filter = invoke<filter_impl<P, T>>;
/**
* for_each
* reference: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3915.pdf
*/
template<typename F, typename Tuple, std::size_t...Is>
constexpr void for_each_in_tuple(Tuple &tuple, F &func, std::index_sequence<Is...>) {
// FIXME: I really don't like this expander business.
using expander = int[];
(void)expander {
0, ((void)func(std::get<Is>(tuple)), 0)...
};
}
template<typename F, typename Tuple>
constexpr void for_each_in_tuple(Tuple &tuple, F &func) {
for_each_in_tuple(tuple, func, std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
template<typename F, template<class...> typename L, typename... Ts>
constexpr void for_each_of(F &func) {
// for_each_in_tuple(rename<L<Ts...>, std::tuple>, func, std::make_index_sequence<std::tuple_size<Tuple>::value>());
for_each_in_tuple(rename<L<Ts...>, std::tuple>, func);
}
template<typename F, typename L>
constexpr void for_each_of(F &func) {
// for_each_in_tuple(rename<L, std::tuple>, func, std::make_index_sequence<std::tuple_size<Tuple>::value>());
for_each_in_tuple(rename<L, std::tuple>, func);
}
/**
* count_if_impl implementation
*/
namespace {
template <typename T, typename L> struct count_if_impl;
template<typename T, typename L>
struct count_if_impl {
static constexpr int type = 0;
};
template<template<class...> class L, typename T, typename T0, typename... Ts>
struct count_if_impl<T, L<T0, Ts...>> {
static constexpr int type = (std::is_same<T, T0>() ? 1 : 0) + count_if_impl<T, L<Ts...>>::type;
};
}
/**
* count_if T exists in L
*/
template<typename T, typename L>
using count_if = std::integral_constant<int, (count_if_impl<T, L>::type)>;
/**
* contains
*/
template<typename T, typename L>
using contains = std::integral_constant<bool, invoke<count_if<T, L>>() >= 1>;
/**
* index_of_impl implementation
*/
namespace {
template<typename T, typename L> struct index_of_impl;
template <typename T, template<class...> typename L, typename... Ts>
struct index_of_impl<T, L<T, Ts...>> {
static constexpr int value = 0;
};
template <typename T, template<class...> typename L>
struct index_of_impl<T, L<>> {
static constexpr int value = -1;
};
template <typename T, template<class...> typename L, typename T0, typename... Ts>
struct index_of_impl<T, L<T0, Ts...>> {
static constexpr int next = index_of_impl<T, L<Ts...>>::value;
static constexpr int value = (next >= 0 ? next + 1 : -1);
};
}
/**
* index_of T in L
*/
template<typename T, typename L>
using index_of = std::integral_constant<int, (index_of_impl<T, L>::value)>;
} // elisa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment