Program Listing for File camp.hpp¶
↰ Return to documentation for file (camp/camp.hpp
)
/*
Copyright (c) 2016-18, Lawrence Livermore National Security, LLC.
Produced at the Lawrence Livermore National Laboratory
Maintained by Tom Scogland <scogland1@llnl.gov>
CODE-756261, All rights reserved.
This file is part of camp.
For details about use and distribution, please read LICENSE and NOTICE from
http://github.com/llnl/camp
*/
#ifndef __CAMP_HPP
#define __CAMP_HPP
#include <type_traits>
#include <camp/defines.hpp>
#include "camp/helpers.hpp"
#include "camp/lambda.hpp"
#include "camp/list.hpp"
#include "camp/make_unique.hpp"
#include "camp/map.hpp"
#include "camp/number.hpp"
#include "camp/size.hpp"
#include "camp/tuple.hpp"
#include "camp/value.hpp"
#include "camp/detail/test.hpp"
namespace camp
{
// Fwd
template <typename Seq>
struct flatten;
// Sequences
template <typename Seq, typename T>
struct append;
template <typename... Elements, typename T>
struct append<list<Elements...>, T> {
using type = list<Elements..., T>;
};
template <typename Seq, typename T>
struct prepend;
template <typename... Elements, typename T>
struct prepend<list<Elements...>, T> {
using type = list<Elements..., T>;
};
template <typename Seq, typename T>
struct extend;
template <typename... Elements, typename... NewElements>
struct extend<list<Elements...>, list<NewElements...>> {
using type = list<Elements..., NewElements...>;
};
namespace detail
{
template <typename CurSeq, size_t N, typename... Rest>
struct flatten_impl;
template <typename CurSeq>
struct flatten_impl<CurSeq, 0> {
using type = CurSeq;
};
template <typename... CurSeqElements,
size_t N,
typename First,
typename... Rest>
struct flatten_impl<list<CurSeqElements...>, N, First, Rest...> {
using type = typename flatten_impl<list<CurSeqElements..., First>,
N - 1,
Rest...>::type;
};
template <typename... CurSeqElements,
size_t N,
typename... FirstInnerElements,
typename... Rest>
struct flatten_impl<list<CurSeqElements...>,
N,
list<FirstInnerElements...>,
Rest...> {
using first_inner_flat =
typename flatten_impl<list<>,
sizeof...(FirstInnerElements),
FirstInnerElements...>::type;
using cur_and_first =
typename extend<list<CurSeqElements...>, first_inner_flat>::type;
using type = typename flatten_impl<cur_and_first, N - 1, Rest...>::type;
};
} // namespace detail
template <typename... Elements>
struct flatten<list<Elements...>>
: detail::flatten_impl<list<>, sizeof...(Elements), Elements...> {
};
template <typename... Seqs>
struct join;
template <typename Seq1, typename Seq2, typename... Rest>
struct join<Seq1, Seq2, Rest...> {
using type = typename join<typename extend<Seq1, Seq2>::type, Rest...>::type;
};
template <typename Seq1>
struct join<Seq1> {
using type = Seq1;
};
template <>
struct join<> {
using type = list<>;
};
template <template <typename...> class Op, typename T>
struct transform;
template <template <typename...> class Op, typename... Elements>
struct transform<Op, list<Elements...>> {
using type = list<typename Op<Elements>::type...>;
};
namespace detail
{
template <template <typename...> class Op, typename Current, typename... Rest>
struct accumulate_impl;
template <template <typename...> class Op,
typename Current,
typename First,
typename... Rest>
struct accumulate_impl<Op, Current, First, Rest...> {
using current = typename Op<Current, First>::type;
using type = typename accumulate_impl<Op, current, Rest...>::type;
};
template <template <typename...> class Op, typename Current>
struct accumulate_impl<Op, Current> {
using type = Current;
};
} // namespace detail
template <template <typename...> class Op, typename Initial, typename Seq>
struct accumulate;
template <template <typename...> class Op,
typename Initial,
typename... Elements>
struct accumulate<Op, Initial, list<Elements...>> {
using type = typename detail::accumulate_impl<Op, Initial, Elements...>::type;
};
namespace detail
{
template<class, class>
struct product_impl{};
template<class... Xs, class... Ys>
struct product_impl<list<Xs...>, list<Ys...>> {
using type = list<list<Xs..., Ys>...>;
};
template<class, class>
struct product{};
template<class... Seqs, class... vals>
struct product<list<Seqs...>, list<vals...>> {
using type = typename join<typename product_impl<Seqs, list<vals...>>::type...>::type;
};
} /* detail */
template<class ... Seqs>
using cartesian_product = typename accumulate<detail::product, list<list<>>, list<Seqs...>>::type;
CAMP_MAKE_L(accumulate);
template <typename T, typename L>
struct index_of;
template <typename T, typename... Elements>
struct index_of<T, list<Elements...>> {
template <typename Seq, typename Item>
using inc_until =
if_<typename std::is_same<T, Item>::type,
if_c<size<Seq>::value == 1,
typename prepend<Seq, num<first<Seq>::value>>::type,
Seq>,
list<num<first<Seq>::value + 1>>>;
using indices =
typename accumulate<inc_until, list<num<0>>, list<Elements...>>::type;
using type =
typename if_c<size<indices>::value == 2, first<indices>, camp::nil>::type;
};
template <template <typename...> class Op, typename Seq>
struct filter;
template <template <typename...> class Op, typename... Elements>
struct filter<Op, list<Elements...>> {
template <typename Seq, typename T>
using append_if =
if_<typename Op<T>::type, typename append<Seq, T>::type, Seq>;
using type = typename accumulate<append_if, list<>, list<Elements...>>::type;
};
CAMP_MAKE_L(filter);
template <typename T, T... Args>
struct size<int_seq<T, Args...>> {
constexpr static idx_t value{sizeof...(Args)};
using type = num<sizeof...(Args)>;
};
} // end namespace camp
#endif /* __CAMP_HPP */