LCOV - code coverage report
Current view: top level - clang/tools/extra/clangd - Function.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 0 10 0.0 %
Date: 2018-02-23 05:02:05 Functions: 0 72 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- Function.h - Utility callable wrappers  -----------------*- C++-*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file provides an analogue to std::function that supports move semantics.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
      15             : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
      16             : 
      17             : #include "llvm/ADT/STLExtras.h"
      18             : #include <cassert>
      19             : #include <memory>
      20             : #include <tuple>
      21             : #include <type_traits>
      22             : #include <utility>
      23             : 
      24             : namespace clang {
      25             : namespace clangd {
      26             : 
      27             : /// A move-only type-erasing function wrapper. Similar to `std::function`, but
      28             : /// allows to store move-only callables.
      29             : template <class> class UniqueFunction;
      30             : 
      31             : template <class Ret, class... Args> class UniqueFunction<Ret(Args...)> {
      32             : public:
      33             :   UniqueFunction() = default;
      34             :   UniqueFunction(std::nullptr_t) : UniqueFunction(){};
      35             : 
      36             :   UniqueFunction(UniqueFunction const &) = delete;
      37             :   UniqueFunction &operator=(UniqueFunction const &) = delete;
      38             : 
      39             :   UniqueFunction(UniqueFunction &&) noexcept = default;
      40             :   UniqueFunction &operator=(UniqueFunction &&) noexcept = default;
      41             : 
      42             :   template <class Callable,
      43             :             /// A sfinae-check that Callable can be called with Args... and
      44             :             class = typename std::enable_if<std::is_convertible<
      45             :                 decltype(std::declval<Callable>()(std::declval<Args>()...)),
      46             :                 Ret>::value>::type>
      47           0 :   UniqueFunction(Callable &&Func)
      48             :       : CallablePtr(llvm::make_unique<
      49             :                     FunctionCallImpl<typename std::decay<Callable>::type>>(
      50           0 :             std::forward<Callable>(Func))) {}
      51             : 
      52             :   explicit operator bool() { return bool(CallablePtr); }
      53             : 
      54             :   Ret operator()(Args... As) {
      55             :     assert(CallablePtr);
      56             :     return CallablePtr->Call(std::forward<Args>(As)...);
      57             :   }
      58             : 
      59             : private:
      60             :   class FunctionCallBase {
      61             :   public:
      62             :     virtual ~FunctionCallBase() = default;
      63             :     virtual Ret Call(Args... As) = 0;
      64             :   };
      65             : 
      66             :   template <class Callable>
      67           0 :   class FunctionCallImpl final : public FunctionCallBase {
      68             :     static_assert(
      69             :         std::is_same<Callable, typename std::decay<Callable>::type>::value,
      70             :         "FunctionCallImpl must be instanstiated with std::decay'ed types");
      71             : 
      72             :   public:
      73           0 :     FunctionCallImpl(Callable Func) : Func(std::move(Func)) {}
      74             : 
      75           0 :     Ret Call(Args... As) override { return Func(std::forward<Args>(As)...); }
      76             : 
      77             :   private:
      78             :     Callable Func;
      79             :   };
      80             : 
      81             :   std::unique_ptr<FunctionCallBase> CallablePtr;
      82             : };
      83             : 
      84             : /// Stores a callable object (Func) and arguments (Args) and allows to call the
      85             : /// callable with provided arguments later using `operator ()`. The arguments
      86             : /// are std::forward'ed into the callable in the body of `operator()`. Therefore
      87             : /// `operator()` can only be called once, as some of the arguments could be
      88             : /// std::move'ed into the callable on first call.
      89             : template <class Func, class... Args> struct ForwardBinder {
      90             :   using Tuple = std::tuple<typename std::decay<Func>::type,
      91             :                            typename std::decay<Args>::type...>;
      92             :   Tuple FuncWithArguments;
      93             : #ifndef NDEBUG
      94             :   bool WasCalled = false;
      95             : #endif
      96             : 
      97             : public:
      98             :   ForwardBinder(Tuple FuncWithArguments)
      99             :       : FuncWithArguments(std::move(FuncWithArguments)) {}
     100             : 
     101             : private:
     102             :   template <std::size_t... Indexes, class... RestArgs>
     103           0 :   auto CallImpl(llvm::integer_sequence<std::size_t, Indexes...> Seq,
     104             :                 RestArgs &&... Rest)
     105             :       -> decltype(std::get<0>(this->FuncWithArguments)(
     106             :           std::forward<Args>(std::get<Indexes + 1>(this->FuncWithArguments))...,
     107             :           std::forward<RestArgs>(Rest)...)) {
     108           0 :     return std::get<0>(this->FuncWithArguments)(
     109             :         std::forward<Args>(std::get<Indexes + 1>(this->FuncWithArguments))...,
     110           0 :         std::forward<RestArgs>(Rest)...);
     111             :   }
     112             : 
     113             : public:
     114             :   template <class... RestArgs>
     115             :   auto operator()(RestArgs &&... Rest)
     116             :       -> decltype(this->CallImpl(llvm::index_sequence_for<Args...>(),
     117             :                                  std::forward<RestArgs>(Rest)...)) {
     118             : 
     119             : #ifndef NDEBUG
     120             :     assert(!WasCalled && "Can only call result of BindWithForward once.");
     121             :     WasCalled = true;
     122             : #endif
     123           0 :     return CallImpl(llvm::index_sequence_for<Args...>(),
     124             :                     std::forward<RestArgs>(Rest)...);
     125             :   }
     126             : };
     127             : 
     128             : /// Creates an object that stores a callable (\p F) and first arguments to the
     129             : /// callable (\p As) and allows to call \p F with \Args at a later point.
     130             : /// Similar to std::bind, but also works with move-only \p F and \p As.
     131             : ///
     132             : /// The returned object must be called no more than once, as \p As are
     133             : /// std::forwarded'ed (therefore can be moved) into \p F during the call.
     134             : template <class Func, class... Args>
     135             : ForwardBinder<Func, Args...> BindWithForward(Func F, Args &&... As) {
     136             :   return ForwardBinder<Func, Args...>(
     137           0 :       std::make_tuple(std::forward<Func>(F), std::forward<Args>(As)...));
     138             : }
     139             : 
     140             : } // namespace clangd
     141             : } // namespace clang
     142             : 
     143             : #endif

Generated by: LCOV version 1.13