pfor/src/pfor/index/index.h

74 lines
1.6 KiB
C++

#ifndef PFOR_PFOR_INDEX_INDEX_H
#define PFOR_PFOR_INDEX_INDEX_H
#include "../mp/meta.h"
#include "../mp/pack.h"
#include "op.h"
#include "tag.h"
namespace pfor {
namespace index {
using Value = long;
/**
* @param first the expression
* @param second a list of properties
*/
template<typename, typename> struct IndexImpl;
template<typename... ExprArgs>
using IndexImplExpr = IndexImpl<Pack<ExprArgs...>, Pack<>>;
template<typename P>
struct IndexImpl<Pack<>, P> {
using IsIndex = tag::Index;
using Properties = P;
inline static Value eval(Value i) { return i; }
};
template<Value n, typename P>
struct IndexImpl<Pack<IntToType<n>>, P> {
using IsIndex = tag::Index;
using Properties = P;
inline static Value eval(Value) { return n; }
};
template<typename Op, typename... Ts, typename P>
struct IndexImpl<Pack<Op, IndexImpl<Ts...>>, P> {
using IsIndex = tag::Index;
using Index = IndexImpl<Ts...>;
using Properties = P;
inline static Value eval(Value i) { return Op::eval(Index::eval(i)); }
};
template<typename Op, typename... LTs, typename... RTs, typename P>
struct IndexImpl<Pack<Op, IndexImpl<LTs...>, IndexImpl<RTs...>>, P> {
using IsIndex = tag::Index;
using LIndex = IndexImpl<LTs...>;
using RIndex = IndexImpl<RTs...>;
using Properties = P;
inline static Value eval(Value i) { return Op::eval(LIndex::eval(i), RIndex::eval(i)); }
};
template<Value n, typename P = Pack<>>
using Index = IndexImpl<Pack<IntToType<n>>, P>;
}
template<typename P = Pack<>>
using IndexP = index::IndexImpl<Pack<>, P>;
using Index = IndexP<>;
template<index::Value n, typename P = Pack<>>
constexpr index::Index<n, P> ctv;
}
#endif