139 lines
6.1 KiB
C++
139 lines
6.1 KiB
C++
// tmp_policy
|
|
// Created by lucas on 22-7-26.
|
|
// Re-implementation of a typical policy architecture in C++ Template Meta-Programming.
|
|
|
|
#ifndef TMP_POLICY_POLICY_FUNDAMENTALS_H
|
|
#define TMP_POLICY_POLICY_FUNDAMENTALS_H
|
|
|
|
#include <type_traits>
|
|
|
|
// The container of policy objects.
|
|
template <typename ...>
|
|
struct PolicyContainer;
|
|
|
|
// This part of logic should not be accessed by the outside code.
|
|
namespace NSPolicySelect {
|
|
|
|
// Auxiliary Meta-Function: template <typename> constexpr bool IsArrayEmpty
|
|
// To indicate whether a PolicyContainer is empty or not.
|
|
// True branch: If the template parameter isn't PolicyContainer,
|
|
// or is a PolicyContainer with no element,
|
|
// the meta-function returns true.
|
|
template <typename T>
|
|
constexpr bool IsArrayEmpty = true;
|
|
|
|
// False branch: If the template parameter is a PolicyContainer
|
|
// with more than one element,
|
|
// the meta-function returns false.
|
|
template <typename TCurrent, typename ... TTypes>
|
|
constexpr bool IsArrayEmpty<PolicyContainer<TCurrent, TTypes...>> = false;
|
|
|
|
// Meta-Function: template <typename, typename> struct MajorFilter_;
|
|
// Remove the policy object whose MajorClass doesn't match with the first policy object.
|
|
// Also, the primitive template handles with the situation in which the two PolicyContainer are both empty.
|
|
template <typename TPolicyContainerModified, typename TPolicyContainerOriginal>
|
|
struct MajorFilter_
|
|
{
|
|
using type = PolicyContainer<>;
|
|
};
|
|
|
|
// Template specialization of MajorFilter_.
|
|
template <typename TFirstPolicy, typename ... TModifiedPolicies,
|
|
typename TCurPolicy, typename ... TOtherPolicies>
|
|
struct MajorFilter_<PolicyContainer<TFirstPolicy, TModifiedPolicies...>,
|
|
PolicyContainer<TCurPolicy, TOtherPolicies...>>
|
|
{
|
|
// The main logic of the loop.
|
|
// Use std::conditional_t to perform branch structure.
|
|
using type = std::conditional_t<
|
|
// Condition: Does TCurPolicy contain the same major class as the policy group?
|
|
std::is_same<typename TFirstPolicy::MajorClass, typename TCurPolicy::MajorClass>::value,
|
|
// True branch: If it does, add TCurPolicy to the policy group.
|
|
typename MajorFilter_<PolicyContainer<TFirstPolicy, TModifiedPolicies..., TCurPolicy>,
|
|
PolicyContainer<TOtherPolicies...>>::type,
|
|
// False branch: If it doesn't, skip TCurPolicy.
|
|
typename MajorFilter_<PolicyContainer<TFirstPolicy, TModifiedPolicies...>,
|
|
PolicyContainer<TOtherPolicies...>>::type
|
|
>;
|
|
// ... and recursively proceed with next element.
|
|
};
|
|
|
|
// Template specialization of MajorFilter_.
|
|
template <typename TEmptyContainer, typename TFirstPolicy, typename ... TOtherPolicies>
|
|
struct MajorFilter_<TEmptyContainer,
|
|
PolicyContainer<TFirstPolicy, TOtherPolicies...>>
|
|
{
|
|
// The beginning of the recursion.
|
|
// Simply put the first policy into the modified policy container.
|
|
using type = typename MajorFilter_<PolicyContainer<TFirstPolicy>,
|
|
PolicyContainer<TOtherPolicies...>>::type;
|
|
};
|
|
|
|
// Template specialization of MajorFilter_.
|
|
template <typename ... TPolicies, typename TEmptyContainer>
|
|
struct MajorFilter_<PolicyContainer<TPolicies...>, TEmptyContainer>
|
|
{
|
|
// Boundary of recursion: The proceeding policy container has no elements inside.
|
|
// Therefore, simply return the proceeded policy container.
|
|
using type = PolicyContainer<TPolicies...>;
|
|
};
|
|
|
|
// Auxiliary type definition: simplify the usage of MajorFilter_.
|
|
template <typename TPolicyCont>
|
|
using MajorFilter = typename MajorFilter_<PolicyContainer<>, TPolicyCont>::type;
|
|
|
|
// Meta-Function: template <typename, typename> struct MinorCheckInner_.
|
|
// Check whether the rest policy objects' MinorClass match with the current policy object or not.
|
|
// It performs as the inner loop of the minor check algorithm.
|
|
// Also, the primitive template handles with the boundary of recursion.
|
|
// It simply returns std::true_type when there is no policy object in the PolicyContainer.
|
|
template <typename TPolicy, typename TPolicyCont>
|
|
struct MinorCheckInner_
|
|
{
|
|
using type = std::true_type;
|
|
};
|
|
|
|
// Template specialization of MinorCheckInner_.
|
|
template <typename TPolicy, typename TCurPolicy, typename ... TRestPolicies>
|
|
struct MinorCheckInner_<TPolicy, PolicyContainer<TCurPolicy, TRestPolicies...>>
|
|
{
|
|
using type = std::conditional_t<
|
|
// The meta-function checks if two policy objects have the same minor class...
|
|
std::is_same<typename TPolicy::MinorClass, typename TCurPolicy::MinorClass>::value,
|
|
// ... if yes, simply returns false to end the recursion.
|
|
std::false_type,
|
|
// ... if no, proceeds check with TPolicy
|
|
// and the next policy object in the policy container.
|
|
typename MinorCheckInner_<TPolicy, PolicyContainer<TRestPolicies...>>::type
|
|
>;
|
|
};
|
|
|
|
// Meta-Function: template <typename> struct MinorCheckOuter_.
|
|
// For each policy object in the policy container,
|
|
// use MinorCheckInner_ to identify if there are another policy object
|
|
// having identical minor class.
|
|
template <typename TPolicyContainer>
|
|
struct MinorCheckOuter_
|
|
{
|
|
using type = std::true_type;
|
|
};
|
|
|
|
template <typename TCurPolicy, typename ... TRestPolicies>
|
|
struct MinorCheckOuter_<PolicyContainer<TCurPolicy, TRestPolicies...>>
|
|
{
|
|
private:
|
|
using InnerResult_ = typename MinorCheckInner_<TCurPolicy, PolicyContainer<TRestPolicies...>>::type;
|
|
public:
|
|
using type = std::conditional_t<
|
|
InnerResult_::value,
|
|
typename MinorCheckOuter_<PolicyContainer<TRestPolicies...>>::type,
|
|
std::false_type
|
|
>;
|
|
};
|
|
|
|
template <typename TPolicyContainer>
|
|
constexpr bool MinorCheck = MinorCheckOuter_<TPolicyContainer>::type::value;
|
|
}
|
|
|
|
#endif //TMP_POLICY_POLICY_FUNDAMENTALS_H
|