pfor/src/pfor/index/property/traits.h

159 lines
4.0 KiB
C++

#ifndef PFOR_PFOR_INDEX_PROPERTY_TRAITS_H
#define PFOR_PFOR_INDEX_PROPERTY_TRAITS_H
#include "../../mp/pack.h"
#include "../index.h"
namespace pfor {
namespace index {
/**
* @brief test if a property set contains another property set
*
* @param P the property set
* @param Q the tested property set
*
* @return true if Q in P
*/
template<typename P, typename Q>
struct ContainsProperties {
static constexpr bool value = If<isPack<P>, PackContainsAll<P, Q>, std::false_type>::value;
};
template<typename P, typename Q>
constexpr bool containsProperties = ContainsProperties<P, Q>::value;
/**
* @brief test if an index has some properties
*
* @param Index the index
* @param Q the property set
*
* @return true if the Index properties contain Q
*/
template<typename, typename> struct HasProperties: std::false_type {};
template<typename Expr, typename Prop, typename Q>
struct HasProperties<IndexImpl<Expr, Prop>, Q> {
static constexpr bool value = containsProperties<Prop, Q>;
};
template<typename Index, typename Q>
constexpr bool hasProperties = HasProperties<Index, Q>::value;
/**
* @brief computes new properties
*
* @param P a property of L
* @param O operator
* @param L left properties
* @param R right properties
*
* @return new properties
*/
template<typename, typename, typename, typename>
struct ComputeProperty {
using type = Pack<>;
};
template<typename P, typename O, typename L, typename R>
using ComputePropertyT = typename ComputeProperty<P, O, L, R>::type;
/**
* @brief computes new properties
*
* @param P a property of S
* @param S the properties set
*
* @return infered properties
*/
template<typename, typename>
struct InferProperty {
using type = Pack<>;
};
template<typename P, typename S>
using InferPropertyT = typename InferProperty<P, S>::type;
template<typename, typename, typename, typename> struct GeneratePropertiesImpl;
template<typename O, typename LH, typename... Ls, typename L, typename R>
struct GeneratePropertiesImpl<O, Pack<LH, Ls...>, L, R> {
using type = PackUnion<ComputePropertyT<LH, O, L, R>, typename GeneratePropertiesImpl<O, Pack<Ls...>, L, R>::type>;
};
template<typename O, typename L, typename R>
struct GeneratePropertiesImpl<O, Pack<>, L, R> {
using type = Pack<>;
};
template<typename O, typename L, typename R>
using GenerateProperties = typename GeneratePropertiesImpl<O, L, L, R>::type;
template<typename, typename> struct InferPropertiesImpl;
template<typename H, typename... Ts, typename S>
struct InferPropertiesImpl<Pack<H, Ts...>, S> {
using type = PackUnion<InferPropertyT<H, S>, typename InferPropertiesImpl<Pack<Ts...>, S>::type>;
};
template<typename S>
struct InferPropertiesImpl<Pack<>, S> {
using type = Pack<>;
};
template<typename S>
using InferProperties = typename InferPropertiesImpl<S, S>::type;
/**
* @brief computes new properties
*
* @param O operator
* @param L left properties
* @param R right properties
*
* @return new properties
*/
template<typename O, typename L, typename R>
struct ComputePropertiesImpl {
using NewProperties = GenerateProperties<O, L, R>;
template<typename P, bool=true> struct InferWhileNewProperties;
template<typename P>
struct InferWhileNewProperties<P, true> {
using InferedProperties = InferProperties<P>;
using NewProperties = PackUnion<P, InferedProperties>;
using type = typename InferWhileNewProperties<NewProperties, (packSize<NewProperties> > packSize<P>)>::type;
};
template<typename P>
struct InferWhileNewProperties<P, false> {
using type = P;
};
using type = typename InferWhileNewProperties<NewProperties>::type;
};
template<typename O, typename L, typename R>
using ComputeProperties = typename ComputePropertiesImpl<O, L, R>::type;
/**
* @brief adds properties to the properties set
*
* @param S the properties set
* @param P the new properties to add
*
* @return the new set of properties, including inferred properties
*/
template<typename S, typename P>
using AddProperties = PackUnion<S, P, InferProperties<PackUnion<S, P>>>;
}
}
#endif