/** * Copyright (C) 2018-present MongoDB, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the Server Side Public License, version 1, * as published by MongoDB, Inc. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Server Side Public License for more details. * * You should have received a copy of the Server Side Public License * along with this program. If not, see * . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the Server Side Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #pragma once #include #include "mongo/config.h" namespace mongo { namespace stdx { using ::std::enable_if_t; } // namespace stdx } // namespace mongo // TODO: Deal with importing this from C++20, when the time comes. namespace mongo { namespace stdx { template struct type_identity { using type = T; }; template using type_identity_t = typename type_identity::type; template struct remove_cvref { using type = std::remove_cv_t>; }; template using remove_cvref_t = typename remove_cvref::type; } // namespace stdx } // namespace mongo // TODO: Re-evaluate which of these we need when making the cutover to C++17. namespace mongo { namespace stdx { namespace detail { template struct make_void { using type = void; }; } // namespace detail template using void_t = typename detail::make_void::type; template using bool_constant = std::integral_constant; template struct negation : stdx::bool_constant {}; template struct disjunction : std::false_type {}; template struct disjunction : B {}; template struct disjunction : std::conditional_t> {}; template struct conjunction : std::true_type {}; template struct conjunction : B {}; template struct conjunction : std::conditional_t, B1> {}; } // namespace stdx } // namespace mongo // TS2's `std::experimental::is_detected` and related traits. // See https://en.cppreference.com/w/cpp/experimental/is_detected // // It's a utility for concisely writing traits. It allows a simple // `Op<...>` alias template to be interrogated for substitution // failure, and a few related utilities cover common uses of it. // // Examples: // template // using HasAValueTypeOp = typename T::value_type; // // template // constexpr bool hasAValueType = stdx::is_detected_v; // // // You can also access what the Op's type result was if it succeeds. // // If it fails, the typedef will be the sentinel `stdx::nonesuch` type. // template // using InThatCaseWhatWasIt = stdx::is_detected_t; // // // Or provide your own default: // template // using ValueTypeOrVoid = stdx::is_detected_or_t; // // This std::experimental TS2 API may or may not be present in // toolchain, so it's simplest to provide a full implementation // here until such time as it's available in `std::` or the trait // creation niche is filled by simpler language features (e.g. // `concept`) and we all migrate off of direct SFINAE. namespace mongo::stdx { namespace detail { template class Op, typename... Args> struct Detector { using value_t = std::false_type; using type = Default; }; template class Op, typename... Args> struct Detector>, Op, Args...> { using value_t = std::true_type; using type = Op; }; } // namespace detail struct nonesuch { nonesuch() = delete; ~nonesuch() = delete; nonesuch(const nonesuch&) = delete; nonesuch& operator=(const nonesuch&) = delete; }; template