/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FRUIT_META_VECTOR_H #define FRUIT_META_VECTOR_H #include #include #include #include #include #include namespace fruit { namespace impl { namespace meta { // Used to pass around a Vector, no meaning per se. template struct Vector {}; // Using ConsVector(MetaExpr...) instead of Vector in a meta-expression allows the // types to be evaluated. Avoid using Vector<...> directly in a meta-expression, unless you're sure // that the arguments have already been evaluated (e.g. if Args... are arguments of a metafunction, // Vector is ok but Vector is wrong. struct ConsVector { template struct apply { using type = Vector; }; }; struct GenerateIntSequenceEvenHelper { template struct apply; template struct apply...>> { using type = Vector..., Int...>; }; }; struct GenerateIntSequenceOddHelper { template struct apply; template struct apply...>> { using type = Vector..., Int, Int...>; }; }; struct GenerateIntSequence { template struct apply { using type = If(Bool<(N::value % 2) == 0>, GenerateIntSequenceEvenHelper(GenerateIntSequence(Int)), GenerateIntSequenceOddHelper(GenerateIntSequence(Int))); }; }; template <> struct GenerateIntSequence::apply> { using type = Vector<>; }; template <> struct GenerateIntSequence::apply> { using type = Vector>; }; struct IsInVector { template struct AlwaysFalseBool { constexpr static bool value = false; }; template struct BoolVector; template struct apply; template struct apply> { using type = Bool< !std::is_same::value...>, BoolVector::value...>>::value>; }; }; struct IsVectorContained { template struct apply; template struct AlwaysTrueBool { constexpr static bool value = true; }; template struct BoolVector; template struct apply, V2> { using type = Bool::value...>, BoolVector::type>::value...>>::value>; }; }; struct VectorSize { template struct apply; template struct apply> { using type = Int; }; }; struct PushFront { template struct apply; template struct apply, T> { using type = Vector; }; }; struct PushBack { template struct apply; template struct apply, T> { using type = Vector; }; }; struct ConcatVectors { template struct apply; template struct apply, Vector> { using type = Vector; }; }; struct TransformVector { template struct apply; template struct apply, F> { using type = Vector::type>...>; }; }; struct ReplaceInVectorHelper { template struct apply { using type = T; }; template struct apply { using type = NewElem; }; }; struct ReplaceInVector { template struct apply { using type = TransformVector(V, PartialCall(ReplaceInVectorHelper, ToReplace, NewElem)); }; }; // If V is Vector this calculates F(InitialValue, F(T1, F(..., F(Tn) ...))). // If V is Vector<> this returns InitialValue. struct FoldVector { template struct apply; template struct apply, F, InitialValue> { using type = Fold(F, InitialValue, Ts...); }; }; template using AlwaysVoidPtr = void*; // Returns a copy of V but without the first N elements. // N must be at least 0 and at most VectorSize(V). struct VectorRemoveFirstN { template > struct apply; template struct apply, N, Vector> { template static Vector f(AlwaysVoidPtr..., RemainingTypes*...); using type = decltype(f((Types*)nullptr...)); }; }; struct VectorEndsWith { template struct apply { using N = Int::value - 1>; using type = IsSame(VectorRemoveFirstN(V, N), Vector); }; template struct apply, T> { using type = Bool; }; }; // Removes all None elements from the vector. // O(n) instantiations. struct VectorRemoveNone { template struct apply { using type = Vector<>; }; template struct apply> { using type = PushFront(VectorRemoveNone(Vector), T); }; template struct apply> { using type = VectorRemoveNone(Vector); }; }; struct ConstructErrorWithArgVectorHelper { template struct apply; template struct apply, OtherArgs...> { using type = ConstructError(ErrorTag, OtherArgs..., Args...); }; }; struct ConstructErrorWithArgVector { template struct apply { using type = ConstructErrorWithArgVectorHelper(ErrorTag, VectorRemoveNone(ArgsVector), OtherArgs...); }; }; } // namespace meta } // namespace impl } // namespace fruit #endif // FRUIT_META_VECTOR_H