/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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. */ // @author: Andrei Alexandrescu #pragma once #include #include #include #include #include #include #include namespace folly { template struct tag_t {}; template FOLLY_INLINE_VARIABLE constexpr tag_t tag{}; #if __cpp_lib_bool_constant || _MSC_VER using std::bool_constant; #else // mimic: std::bool_constant, C++17 template using bool_constant = std::integral_constant; #endif template using index_constant = std::integral_constant; // always_false // // A variable template that is always false but requires template arguments to // be provided (which are then ignored). This is useful in very specific cases // where we want type-dependent expressions to defer static_assert's. // // A common use-case is for exhaustive constexpr if branches: // // template // void foo(T value) { // if constexpr (std::is_integral_v) foo_integral(value); // else if constexpr (std::is_same_v) foo_string(value); // else static_assert(always_false, "Unsupported type"); // } // // If we had used static_assert(false), then this would always fail to compile, // even if foo is never instantiated! // // Another use case is if a template that is expected to always be specialized // is erroneously instantiated with the base template. // // template // struct Foo { // static_assert(always_false, "Unsupported type"); // }; // template <> // struct Foo {}; // // Foo a; // fine // Foo b; // fails! And you get a nice (custom) error message // // This is similar to leaving the base template undefined but we get a nicer // compiler error message with static_assert. template FOLLY_INLINE_VARIABLE constexpr bool always_false = false; namespace detail { // is_instantiation_of_v // is_instantiation_of // // A trait variable and type to check if a given type is an instantiation of a // class template. // // Note that this only works with type template parameters. It does not work // with non-type template parameters, template template parameters, or alias // templates. template