Skip to content

Instantly share code, notes, and snippets.

@BlurryLight
Created October 1, 2022 09:34
Show Gist options
  • Save BlurryLight/17c99bb9d6e02dab2f4865b5204d24a3 to your computer and use it in GitHub Desktop.
Save BlurryLight/17c99bb9d6e02dab2f4865b5204d24a3 to your computer and use it in GitHub Desktop.
naive bind c++17
// https://godbolt.org/z/7hefs586j
#include <functional>
#include <tuple>
#include <iostream>
template <size_t n> using index_constant = std::integral_constant<size_t, n>;
template<class ... Args>
class callee_list
{
public:
template<class ... TArgs>
constexpr callee_list(TArgs&&... args) noexcept
: boundedArgs_{std::forward<TArgs>(args)...}
{}
template<class T>
constexpr decltype(auto) operator[](T&& t) noexcept
{
if constexpr (!std::is_placeholder_v<std::decay_t<T>>)
{
return std::forward<T>(t);
}
else
{
constexpr size_t Index = std::is_placeholder<std::decay_t<T>>::value - 1;
return std::get<Index>(std::move(boundedArgs_));
}
}
// Bind以值类型存储所有变量,会擦除int& 到int
std::tuple<typename std::decay_t<Args>...> boundedArgs_;
};
template<class Fn, class ... Args>
class binder
{
public:
template<class TFn, class ... TArgs>
constexpr binder(TFn&& f, TArgs&&... args) noexcept
: f_{std::forward<TFn>(f)},
UnresolvedArgsList_{std::forward<TArgs>(args)...}
{}
template<class ... CallArgs>
constexpr decltype(auto) operator()(CallArgs&&... args)
{
return call(std::make_index_sequence<sizeof...(Args)>{}, std::forward<CallArgs>(args)...);
}
private:
template<class ... CallArgs, size_t ... Seq>
constexpr decltype(auto) call(std::index_sequence<Seq...>, CallArgs&&... args)
{
// 创建callee_List保存调用Operator()时候传入的参数,用于补齐占位符
auto calleeList = callee_list<CallArgs...>{std::forward<CallArgs>(args)...};
// 调用callee_list.operator[]
// Redchards原版:
// 参数折叠展开 f_(calleeList[argumentList_[index_constant<0>{}]],calleeList[argumentList_[index_constant<1>{}]],...);
return f_(calleeList[std::get<index_constant<Seq>{}>(UnresolvedArgsList_)]...);
}
private:
std::function<std::remove_reference_t<std::remove_pointer_t<Fn>>> f_;
// 将占位符以及原有的参数保存在UnResolvedArgsLists_里,在call的时候填充占位符
std::tuple<typename std::decay_t<Args>...> UnresolvedArgsList_;
};
template<class Fn, class ... Args>
// The code is from RedChards https://gist.github.com/Redchards/c5be14c2998f1ca1d757
binder<Fn, Args...> Redchards_Bind(Fn&& f, Args&&... args)
{
return binder<Fn, Args...>{std::forward<Fn>(f), std::forward<Args>(args)...};
}
int foobar(int a,int& b)
{
std::cout << "a: " << a << std::endl;
return ++b;
}
int main()
{
std::cout << "naive bind " << std::endl;
int n = 0;
int& n_ref = n;
auto fn = Redchards_Bind(foobar,1,n_ref);
// bind的引用捕获不能修改外部变量,内部复制了一个值
std::cout << fn() << " " << n << std::endl;
std::cout << fn() << " " << n << std::endl;
}
@BlurryLight
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment