159 lines
4.0 KiB
C++
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
|