// Copyright 2016 Carnegie Mellon University. See LICENSE file for terms. // Author: Michael Duggan #ifndef _MATCHERTAGS_HPP_ #define _MATCHERTAGS_HPP_ // This file contains base tag and tag/type manipulation definitions for use by matcher.hpp. #include namespace matcher { // A holder for types of any type template struct Types { Types() = delete; }; namespace detail { // Base class for TypedTags, so std::is_base_of() can be used. struct TagBase { // Tags are for type tagging only, and are not constructable TagBase() = delete; }; template using IsTag = std::is_base_of; template struct AreTags : std::true_type {}; template struct AreTags : std::conditional::value, AreTags, std::false_type>::type {}; template struct AreTags> : AreTags {}; } // namespace detail // Base of match tag types. This type holds the following information: // // A) subtags, which is a list of tags that this tag has as arguments. This is used by // detail::CountRef. // B) convertible, which is a list of valid capture types for this node. This is used by the // Matcher> implementation. // template struct TypedTag : detail::TagBase { using subtags = Types; using convertible = RefTypes; }; // A simpler version of TypedTag for nodes that have no tag arguments template using Tag = TypedTag>; // Within this next section are operations on Types<> constructions namespace detail { // Determine if type S is one of the types in Rest. If Rest is Types<...>, then it will // determine if S is one of the types in Types<...>. This will be either std::true_type or // std::false_type. template struct HasType; // Base case : false template struct HasType : std::false_type {}; // Inductive step. true if S == T, recurse on Rest otherwise template struct HasType : std::conditional::value, std::true_type, HasType>::type {}; // Convert HasType> to HasType template struct HasType> : HasType {}; // _TypesInCommon determines what types are in common betwen A and B (with accumulator Acc) template > struct _TypesInCommon; // If A has no types, there are no types left in common. Return the accumulator. template struct _TypesInCommon, B, Acc> { using type = Acc; }; // If A has types, see if the first type in A is in B. If so, add it to the accumulator and // recurse. Otherwise, just recurse. template struct _TypesInCommon, B, Types> { using type = typename std::conditional< HasType::value, typename _TypesInCommon, B, Types>::type, typename _TypesInCommon, B, Types>::type>::type; }; // _TypesInCommonN determines what types are in common between the Types<> argments to // _TypesInCommonN. template struct _TypesInCommonN; // The user-friendly version of _TypesInCommonN (doesn't require ::type) template using TypesInCommon = typename _TypesInCommonN::type; // Base case: if only one set of types is left, return it template struct _TypesInCommonN> { using type = Types; }; // Inductive case: Using the types in common between A and B, recurse on T. template struct _TypesInCommonN { using type = TypesInCommon::type, T...>; }; } // namespace detail } // namespace matcher #endif // _MATCHERTAGS_HPP_ /* Local Variables: */ /* mode: c++ */ /* fill-column: 95 */ /* comment-column: 0 */ /* c-basic-offset: 2 */ /* End: */