2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <folly/ApplyTuple.h>
26 // helper type to make sure that the templated constructor in Partial does
27 // not accidentally act as copy or move constructor
28 struct PartialConstructFromCallable {};
30 template <typename F, typename Tuple>
37 template <typename Callable, typename... Args>
38 Partial(PartialConstructFromCallable, Callable&& callable, Args&&... args)
39 : f_(std::forward<Callable>(callable)),
40 stored_args_(std::forward<Args>(args)...) {}
42 template <typename... CArgs>
43 auto operator()(CArgs&&... cargs) & -> decltype(applyTuple(
45 static_cast<Tuple&>(stored_args_),
46 std::forward_as_tuple(std::forward<CArgs>(cargs)...))) {
49 static_cast<Tuple&>(stored_args_),
50 std::forward_as_tuple(std::forward<CArgs>(cargs)...));
53 template <typename... CArgs>
54 auto operator()(CArgs&&... cargs) const& -> decltype(applyTuple(
55 static_cast<F const&>(f_),
56 static_cast<Tuple const&>(stored_args_),
57 std::forward_as_tuple(std::forward<CArgs>(cargs)...))) {
59 static_cast<F const&>(f_),
60 static_cast<Tuple const&>(stored_args_),
61 std::forward_as_tuple(std::forward<CArgs>(cargs)...));
64 template <typename... CArgs>
65 auto operator()(CArgs&&... cargs) && -> decltype(applyTuple(
67 static_cast<Tuple&&>(stored_args_),
68 std::forward_as_tuple(std::forward<CArgs>(cargs)...))) {
71 static_cast<Tuple&&>(stored_args_),
72 std::forward_as_tuple(std::forward<CArgs>(cargs)...));
76 } // namespace partial
80 * Partially applies arguments to a callable
82 * `partial` takes a callable and zero or more additional arguments and returns
83 * a callable object, which when called with zero or more arguments, will invoke
84 * the original callable with the additional arguments passed to `partial`,
85 * followed by those passed to the call.
87 * E.g. `partial(Foo, 1, 2)(3)` is equivalent to `Foo(1, 2, 3)`.
89 * `partial` can be used to bind a class method to an instance:
90 * `partial(&Foo::method, foo_pointer)` returns a callable object that can be
91 * invoked in the same way as `foo_pointer->method`. In case the first
92 * argument in a call to `partial` is a member pointer, the second argument
93 * can be a reference, pointer or any object that can be dereferenced to
94 * an object of type Foo (like `std::shared_ptr` or `std::unique_ptr`).
96 * `partial` is similar to `std::bind`, but you don't have to use placeholders
97 * to have arguments passed on. Any number of arguments passed to the object
98 * returned by `partial` when called will be added to those passed to `partial`
99 * and passed to the original callable.
101 template <typename F, typename... Args>
102 auto partial(F&& f, Args&&... args) -> detail::partial::Partial<
103 typename std::decay<F>::type,
104 std::tuple<typename std::decay<Args>::type...>> {
105 return {detail::partial::PartialConstructFromCallable{},
107 std::forward<Args>(args)...};