// 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 // The container of policy objects. template struct PolicyContainer; // This part of logic should not be accessed by the outside code. namespace NSPolicySelect { // Auxiliary Meta-Function: template 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 constexpr bool IsArrayEmpty = true; // False branch: If the template parameter is a PolicyContainer // with more than one element, // the meta-function returns false. template constexpr bool IsArrayEmpty> = false; // Meta-Function: template 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 struct MajorFilter_ { using type = PolicyContainer<>; }; // Template specialization of MajorFilter_. template struct MajorFilter_, PolicyContainer> { // 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::value, // True branch: If it does, add TCurPolicy to the policy group. typename MajorFilter_, PolicyContainer>::type, // False branch: If it doesn't, skip TCurPolicy. typename MajorFilter_, PolicyContainer>::type >; // ... and recursively proceed with next element. }; // Template specialization of MajorFilter_. template struct MajorFilter_> { // The beginning of the recursion. // Simply put the first policy into the modified policy container. using type = typename MajorFilter_, PolicyContainer>::type; }; // Template specialization of MajorFilter_. template struct MajorFilter_, TEmptyContainer> { // Boundary of recursion: The proceeding policy container has no elements inside. // Therefore, simply return the proceeded policy container. using type = PolicyContainer; }; // Auxiliary type definition: simplify the usage of MajorFilter_. template using MajorFilter = typename MajorFilter_, TPolicyCont>::type; // Meta-Function: template 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 struct MinorCheckInner_ { using type = std::true_type; }; // Template specialization of MinorCheckInner_. template struct MinorCheckInner_> { using type = std::conditional_t< // The meta-function checks if two policy objects have the same minor class... std::is_same::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_>::type >; }; // Meta-Function: template 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 struct MinorCheckOuter_ { using type = std::true_type; }; template struct MinorCheckOuter_> { private: using InnerResult_ = typename MinorCheckInner_>::type; public: using type = std::conditional_t< InnerResult_::value, typename MinorCheckOuter_>::type, std::false_type >; }; template constexpr bool MinorCheck = MinorCheckOuter_::type::value; } #endif //TMP_POLICY_POLICY_FUNDAMENTALS_H