/* * Copyright 2011-present Facebook, Inc. * * 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. */ #pragma once #include #include #include namespace folly { namespace dptr_detail { /** * Given a target type and a list of types, return the 1-based index of the * type in the list of types. Fail to compile if the target type doesn't * appear in the list. * * GetIndex::value == 3 * GetIndex::value -> fails to compile */ template struct GetTypeIndex; // When recursing, we never reach the 0- or 1- template argument base case // unless the target type is not in the list. If the target type is in the // list, we stop recursing when it is at the head of the remaining type // list via the GetTypeIndex partial specialization. template struct GetTypeIndex { static const size_t value = 1; }; template struct GetTypeIndex { static const size_t value = 1 + GetTypeIndex::value; }; // Generalize std::is_same for variable number of type arguments template struct IsSameType; template <> struct IsSameType<> { static const bool value = true; }; template struct IsSameType { static const bool value = true; }; template struct IsSameType { static const bool value = std::is_same::value && IsSameType::value; }; // Define type as the type of all T in (non-empty) Types..., asserting that // all types in Types... are the same. template struct SameType; template struct SameType { typedef T type; static_assert( IsSameType::value, "Not all types in pack are the same"); }; // Determine the result type of applying a visitor of type V on a pointer // to type T. template struct VisitorResult1 { typedef invoke_result_t type; }; // Determine the result type of applying a visitor of type V on a const pointer // to type T. template struct ConstVisitorResult1 { typedef invoke_result_t type; }; // Determine the result type of applying a visitor of type V on pointers of // all types in Types..., asserting that the type is the same for all types // in Types... template struct VisitorResult { typedef typename SameType::type...>::type type; }; // Determine the result type of applying a visitor of type V on const pointers // of all types in Types..., asserting that the type is the same for all types // in Types... template struct ConstVisitorResult { typedef typename SameType::type...>::type type; }; template struct ApplyVisitor1; template struct ApplyVisitor1<1, V, R, T, Types...> { R operator()(size_t, V&& visitor, void* ptr) const { return visitor(static_cast(ptr)); } }; template struct ApplyVisitor1 { R operator()(size_t runtimeIndex, V&& visitor, void* ptr) const { return runtimeIndex == 1 ? visitor(static_cast(ptr)) : ApplyVisitor1()( runtimeIndex - 1, std::forward(visitor), ptr); } }; template struct ApplyConstVisitor1; template struct ApplyConstVisitor1<1, V, R, T, Types...> { R operator()(size_t, V&& visitor, void* ptr) const { return visitor(static_cast(ptr)); } }; template struct ApplyConstVisitor1 { R operator()(size_t runtimeIndex, V&& visitor, void* ptr) const { return runtimeIndex == 1 ? visitor(static_cast(ptr)) : ApplyConstVisitor1()( runtimeIndex - 1, std::forward(visitor), ptr); } }; template using ApplyVisitor = ApplyVisitor1< sizeof...(Types), V, typename VisitorResult::type, Types...>; template using ApplyConstVisitor = ApplyConstVisitor1< sizeof...(Types), V, typename ConstVisitorResult::type, Types...>; } // namespace dptr_detail } // namespace folly