/* * Copyright 2016 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 namespace folly { namespace detail { namespace partial { // helper type to make sure that the templated constructor in Partial does // not accidentally act as copy or move constructor struct PartialConstructFromCallable {}; template class Partial { private: F f_; Tuple stored_args_; public: template Partial(PartialConstructFromCallable, Callable&& callable, Args&&... args) : f_(std::forward(callable)), stored_args_(std::forward(args)...) {} // full auto doesn't work here due to // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70983 :( template auto operator()(CArgs&&... cargs) & -> decltype(applyTuple( static_cast(f_), static_cast(stored_args_), std::forward_as_tuple(std::forward(cargs)...))) { return applyTuple( static_cast(f_), static_cast(stored_args_), std::forward_as_tuple(std::forward(cargs)...)); } template auto operator()(CArgs&&... cargs) const& -> decltype(applyTuple( static_cast(f_), static_cast(stored_args_), std::forward_as_tuple(std::forward(cargs)...))) { return applyTuple( static_cast(f_), static_cast(stored_args_), std::forward_as_tuple(std::forward(cargs)...)); } template auto operator()(CArgs&&... cargs) && -> decltype(applyTuple( static_cast(f_), static_cast(stored_args_), std::forward_as_tuple(std::forward(cargs)...))) { return applyTuple( static_cast(f_), static_cast(stored_args_), std::forward_as_tuple(std::forward(cargs)...)); } }; } // namespace partial } // namespace detail /** * Partially applies arguments to a callable * * `partial` takes a callable and zero or more additional arguments and returns * a callable object, which when called with zero or more arguments, will invoke * the original callable with the additional arguments passed to `partial`, * followed by those passed to the call. * * E.g. `partial(Foo, 1, 2)(3)` is equivalent to `Foo(1, 2, 3)`. * * `partial` can be used to bind a class method to an instance: * `partial(&Foo::method, foo_pointer)` returns a callable object that can be * invoked in the same way as `foo_pointer->method`. In case the first * argument in a call to `partial` is a member pointer, the second argument * can be a reference, pointer or any object that can be dereferenced to * an object of type Foo (like `std::shared_ptr` or `std::unique_ptr`). * * `partial` is similar to `std::bind`, but you don't have to use placeholders * to have arguments passed on. Any number of arguments passed to the object * returned by `partial` when called will be added to those passed to `partial` * and passed to the original callable. */ template auto partial(F&& f, Args&&... args) -> detail::partial::Partial< typename std::decay::type, std::tuple::type...>> { return {detail::partial::PartialConstructFromCallable{}, std::forward(f), std::forward(args)...}; } } // namespace folly