这里是最初始的版本,参考https://github.com/cplusplus-study/fork_stl/blob/master/include/bind.hpp 提供了最简洁的实现方式。

第一部分是bind的实现代码, 第二部分是测试代码, 对bind的实现代码中有疑问或不明白的,可参考测试代码, 测试代码基本说明了某个代码的基本含义和用途。

1. 实现

 ///////////////////////////////////////////////////////////////////////////////
// std::bind\boost::bind的山寨版本, 主要学习用.
#include <stdlib.h>
#include <type_traits>
#include <utility>
#include <tuple>
#include <functional> namespace xusd{
template <int NUM> struct placeholder{ }; template <typename T> struct is_placeholder;
template <int NUM> struct is_placeholder<placeholder<NUM> >{ enum{ value = NUM }; };
template <typename T> struct is_placeholder{ enum{ value = }; }; template <int ...N> struct seq{ };
template <unsigned N, unsigned...S> struct gen;
template <unsigned N, unsigned...S> struct gen: gen<N-, N-, S...>{ };
template <unsigned...S> struct gen<, S...>{ typedef seq<S...> type; }; template <int N, typename B, typename C>
typename std::tuple_element<
N,
typename std::decay<B>::type
>::type
select(std::false_type, B&& b, C&& c){
return std::get<N>(b);
} template <int N, typename B, typename C>
typename std::tuple_element<
is_placeholder<
typename std::tuple_element<
N,
typename std::decay<B>::type
>::type
>::value == ? :
is_placeholder<
typename std::tuple_element<
N,
typename std::decay<B>::type
>::type
>::value - ,
typename std::decay<C>::type
>::type
select(std::true_type, B&& b, C&& c)
{
return std::get<
is_placeholder<
typename std::tuple_element<
N,
typename std::decay<B>::type
>::type
>::value -
>(c);
} template <typename Fun> struct GetResult{
typedef typename std::enable_if<
std::is_class<
typename std::decay<Fun>::type
>::value,
typename GetResult<
decltype(&Fun::operator())
>::result_type
>::type result_type;
}; template <typename R, typename... Args>
struct GetResult<R(Args...)>{
typedef R result_type;
};
template <typename C, typename R, typename... Args>
struct GetResult<R(C::*)(Args...)>{
typedef R result_type;
};
template <typename C, typename R, typename... Args>
struct GetResult<R(C::*)(Args...)const>{
typedef R result_type;
}; template <typename C, typename R>
struct GetResult<R(C::*)>{
typedef decltype(((C*))->*((R(C::*)))) result_type;
}; template<typename F, typename... Args>
class bind_t {
typedef std::tuple<typename std::decay<Args>::type...> BindArgs;
typedef typename std::decay<F>::type CallFun;
enum class BindType { MemberFunction = , MemberObject = , Other = }; public:
typedef typename GetResult<
typename std::remove_pointer<
typename std::remove_reference<F>::type
>::type
>::result_type result_type; bind_t(F fun, Args... args):_fun(fun), _bindArgs(args...){ } template<typename... CArgs>
result_type operator()(CArgs&&... c){
std::tuple<CArgs...> cargs(c...);
return callFunc(
std::integral_constant<
int,
std::is_member_function_pointer<CallFun>::value ? : std::is_member_object_pointer<CallFun>::value ? :
>(),
cargs,
typename gen<
std::tuple_size<BindArgs>::value - std::is_member_function_pointer<CallFun>::value
>::type()
);
} private:
template<typename T, int ...S>
result_type callFunc(std::integral_constant<int, >, T&& t, seq<S...>) {
return _fun(
select<S>(
std::integral_constant<
bool,
is_placeholder<
typename std::tuple_element<S, BindArgs>::type
>::value !=
>(),
_bindArgs,
t)...
);
} template<typename T, int ...S>
result_type callFunc(std::integral_constant<int, >, T&& t, seq<S...>) {
return select<>(
std::integral_constant<
bool,
is_placeholder<
typename std::tuple_element<
,
BindArgs
>::type
>::value !=
>(),
_bindArgs,
t)->*_fun;
} template<typename T, int ...S>
result_type callFunc(std::integral_constant<int, >, T&& t, seq<S...>) {
return (
select<>(
std::integral_constant<
bool,
is_placeholder<
typename std::tuple_element<
,
BindArgs
>::type
>::value !=
>(),
_bindArgs,
t)->*_fun
)
(
select<S + >(
std::integral_constant<
bool,
is_placeholder<
typename std::tuple_element<
S + ,
BindArgs
>::type
>::value !=
>(),
_bindArgs,
t
)...
);
} private:
CallFun _fun;
BindArgs _bindArgs;
}; template <typename F, typename... Args>
bind_t<typename std::decay<F>::type, typename std::decay<Args&&>::type...>
bind(F f, Args&&... args){
return bind_t<
typename std::decay<F>::type,
typename std::decay<Args&&>::type...
>(f, args...);
} extern placeholder<> _1;
extern placeholder<> _2;
extern placeholder<> _3;
extern placeholder<> _4;
extern placeholder<> _5;
extern placeholder<> _6;
extern placeholder<> _7;
extern placeholder<> _8;
extern placeholder<> _9;
extern placeholder<> _10;
extern placeholder<> _11;
extern placeholder<> _12;
extern placeholder<> _13;
extern placeholder<> _14;
extern placeholder<> _15;
extern placeholder<> _16;
extern placeholder<> _17;
extern placeholder<> _18;
extern placeholder<> _19;
extern placeholder<> _20;
extern placeholder<> _21;
extern placeholder<> _22;
extern placeholder<> _23;
extern placeholder<> _24;
}

2. 测试

///////////////////////////////////////////////////////////////////////////////
// 以下开始为测试代码. #include <cstdlib>
#include <string>
#include <iostream>
#include <gtest/gtest.h> int add3(int x, int y, int z){
return x + y + z;
} std::string to_string(std::string s1, std::string s2, std::string s3){
return s1 + s2 + s3;
} int g_test_voidfun =;
void voidfun(){
g_test_voidfun = ;
} class MyTest{
public:
std::string to_string(std::string s1, std::string s2, std::string s3){
return s1 + s2 + s3;
}
int add3(int x, int y, int z){
return x + y + z;
} int cadd3(int x, int y, int z) const {
return x + y + z;
}
void voidfun(){
g_test_voidfun = ;
}
void constfun() const {
g_test_voidfun = ;
} int memObj = ;
std::string memObj2;
}; class TestAddFuncter{
public:
int operator()(int x, int y){
return x + y;
}
}; TEST(TestSeq,Test1){
using namespace xusd;
EXPECT_TRUE((std::is_same<gen<>::type, seq<> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,,,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,,,,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,,,,,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,,,,,,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,,,,,,,> >::value));
EXPECT_TRUE((std::is_same<gen<>::type, seq<,,,,,,,,,> >::value));
} TEST(TestPlaceHolder, Test1){
using namespace xusd;
EXPECT_TRUE((std::is_same<decltype(_1), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_2), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_3), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_4), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_5), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_6), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_7), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_8), placeholder<> >::value));
EXPECT_TRUE((std::is_same<decltype(_9), placeholder<> >::value)); EXPECT_EQ(, (is_placeholder<int>::value));
EXPECT_EQ(, (is_placeholder<class A>::value));
EXPECT_EQ(, (is_placeholder<decltype(_1)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_2)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_3)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_4)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_5)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_6)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_7)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_8)>::value));
EXPECT_EQ(, (is_placeholder<decltype(_9)>::value));
} TEST(TestSelectArgs, Test1){
using namespace xusd;
auto b = std::make_tuple(,_1,,_2,,_3,,_4);
auto c = std::make_tuple(,,,); EXPECT_EQ(, (select<>(std::false_type(), b, c)));
EXPECT_EQ(, (select<>(std::true_type(), b, c)));
EXPECT_EQ(, (select<>(std::false_type(), b, c)));
EXPECT_EQ(, (select<>(std::true_type(), b, c)));
EXPECT_EQ(, (select<>(std::false_type(), b, c)));
EXPECT_EQ(, (select<>(std::true_type(), b, c)));
EXPECT_EQ(, (select<>(std::false_type(), b, c)));
EXPECT_EQ(, (select<>(std::true_type(), b, c)));
} TEST(TestGetResult, Test1){
using namespace xusd; class Ret;
class C;
class Args;
class Mem;
EXPECT_TRUE((std::is_same<void,xusd::GetResult<void()>::result_type>::value));
EXPECT_TRUE((std::is_same<int,xusd::GetResult<int(int)>::result_type>::value));
EXPECT_TRUE((std::is_same<const int,xusd::GetResult<const int()>::result_type>::value));
EXPECT_TRUE((std::is_same<Ret,xusd::GetResult<Ret(Args)>::result_type>::value));
EXPECT_TRUE((std::is_same<Ret,xusd::GetResult<Ret(C::*)(Args)>::result_type>::value));
EXPECT_TRUE((std::is_same<Mem&,xusd::GetResult<Mem(C::*)>::result_type>::value)); const MyTest t1;
EXPECT_TRUE((std::is_same<int,decltype(t1.memObj)>::value));
} #define DT(x) decltype(x)
TEST(TestBind_t, Test1){
using namespace xusd;
EXPECT_TRUE((std::is_same<void, bind_t<void ()>::result_type>::value));
EXPECT_TRUE((std::is_same<void, bind_t<void (char), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<void, bind_t<void (char,short), DT((_1)), DT((_2))>::result_type>::value));
EXPECT_TRUE((std::is_same<void, bind_t<void (char,short, int), DT((_1)), DT((_2)), DT((_3))>::result_type>::value));
EXPECT_TRUE((std::is_same<void, bind_t<void (char,short, int, long), DT((_1)), DT((_2)), DT((_3)), DT((_4))>::result_type>::value));
EXPECT_TRUE((std::is_same<void, bind_t<void (char,short, int, long, long long), DT((_1)), DT((_2)), DT((_3)), DT((_4)), DT((_5))>::result_type>::value)); EXPECT_TRUE((std::is_same<int, bind_t<int ()>::result_type>::value));
EXPECT_TRUE((std::is_same<int, bind_t<int (char), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<int, bind_t<int (char,short), DT((_1)), DT((_2))>::result_type>::value));
EXPECT_TRUE((std::is_same<int, bind_t<int (char,short, int), DT((_1)), DT((_2)), DT((_3))>::result_type>::value));
EXPECT_TRUE((std::is_same<int, bind_t<int (char,short, int, long), DT((_1)), DT((_2)), DT((_3)), DT((_4))>::result_type>::value));
EXPECT_TRUE((std::is_same<int, bind_t<int (char,short, int, long, long long), DT((_1)), DT((_2)), DT((_3)), DT((_4)), DT((_5))>::result_type>::value)); EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA ()>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (char), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (char,short), DT((_1)), DT((_2))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (char,short, int), DT((_1)), DT((_2)), DT((_3))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (char,short, int, long), DT((_1)), DT((_2)), DT((_3)), DT((_4))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (char,short, int, long, long long), DT((_1)), DT((_2)), DT((_3)), DT((_4)), DT((_5))>::result_type>::value)); EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (class BBB), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (class BBB, class CCC), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (class BBB, class CCC, class DDD), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (class BBB, class CCC, class DDD, class EEE), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (class BBB, class CCC, class DDD, class EEE, class FFF), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class AAA, bind_t<class AAA (class BBB, class CCC, class DDD, class EEE, class FFF, class GGG), DT((_1))>::result_type>::value)); EXPECT_TRUE((std::is_same<class Ret, bind_t<class Ret (class Arg1), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class Ret, bind_t<class Ret (class Arg1, class Arg2), DT((_2)), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class Ret, bind_t<class Ret (class Arg1, class Arg2, class Arg3), DT((_2)), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class Ret, bind_t<class Ret (class Arg1, class Arg2, class Arg3, class Arg4),DT((_4)), DT((_1))>::result_type>::value));
EXPECT_TRUE((std::is_same<class Ret, bind_t<class Ret (class Arg1, class Arg2, class Arg3, class Arg4, class Arg5), DT((_5))>::result_type>::value));
EXPECT_TRUE((std::is_same<class Ret, bind_t<class Ret (class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6), DT((_6))>::result_type>::value));
} TEST(TestBind_t, Test2){
using namespace xusd;
bind_t<int(int, int, int), DT(_3), DT(_2), DT(_1)> t1(add3, _3, _2, _1);
EXPECT_EQ((add3(, , )), (t1(, , )));
EXPECT_EQ((add3(, , )), (t1(, , ))); bind_t<std::string(std::string, std::string, std::string), DT(_1), DT(_2), DT(_3)> s1(to_string, _1, _2, _3);
bind_t<std::string(std::string, std::string, std::string), DT(_2), DT(_3), DT(_1)> s2(to_string, _2, _3, _1);
bind_t<std::string(std::string, std::string, std::string), DT(_3), DT(_1), DT(_2)> s3(to_string, _3, _1, _2); EXPECT_EQ("", (s1("", "", "")));
EXPECT_EQ("", (s1("", "", "")));
EXPECT_EQ("", (s1("", "", "")));
EXPECT_EQ("2_3", (s1("", "_", "")));
EXPECT_EQ("", (s2("", "", "")));
EXPECT_EQ("", (s3("", "", "")));
} TEST(TestBind, NotMemberFunction){
using namespace xusd;
EXPECT_EQ((add3(, , )), (xusd::bind(add3, _3, _2, _1)(, , )));
EXPECT_EQ((add3(, , )), (xusd::bind(add3, _3, _2, _1)(, , ))); EXPECT_EQ("", (xusd::bind(to_string, _1, _2, _3)("", "", "")));
EXPECT_EQ("", (xusd::bind(to_string, _1, _2, _3)("", "", "")));
EXPECT_EQ("", (xusd::bind(to_string, _1, _2, _3)("", "", "")));
EXPECT_EQ("2_3", (xusd::bind(to_string, _1, _2, _3)("", "_", "")));
EXPECT_EQ("", (xusd::bind(to_string, _2, _3, _1)("", "", "")));
EXPECT_EQ("", (xusd::bind(to_string, _3, _1, _2)("", "", ""))); bind((voidfun))();
EXPECT_EQ(g_test_voidfun, );
} TEST(TestBind, PassToFunctional){
using namespace xusd;
EXPECT_EQ("", (std::function<std::string(std::string, std::string, std::string)>(xusd::bind(to_string, _1, _2, _3))("", "", "")));
EXPECT_EQ("", (std::function<std::string(std::string, std::string, std::string)>(xusd::bind(to_string, _1, _2, _3))("", "", "")));
EXPECT_EQ("", (std::function<std::string(std::string, std::string, std::string)>(xusd::bind(to_string, _1, _2, _3))("", "", "")));
EXPECT_EQ("2_3", (std::function<std::string(std::string, std::string, std::string)>(xusd::bind(to_string, _1, _2, _3))("", "_", "")));
EXPECT_EQ("", (std::function<std::string(std::string, std::string, std::string)>(xusd::bind(to_string, _2, _3, _1))("", "", "")));
EXPECT_EQ("", (std::function<std::string(std::string, std::string, std::string)>(xusd::bind(to_string, _3, _1, _2))("", "", "")));
} TEST(TestBind, TestMumberFunction){
using namespace xusd;
MyTest test;
EXPECT_EQ((add3(, , )), (xusd::bind(&MyTest::add3, &test, _3, _2, _1)(, , )));
EXPECT_EQ((add3(, , )), (xusd::bind(&MyTest::add3, &test, _3, _2, _1)(, , ))); EXPECT_EQ("", (xusd::bind(&MyTest::to_string, &test, _1, _2, _3)("", "", "")));
EXPECT_EQ("", (xusd::bind(&MyTest::to_string, &test, _1, _2, _3)("", "", "")));
EXPECT_EQ("", (xusd::bind(&MyTest::to_string, &test, _1, _2, _3)("", "", "")));
EXPECT_EQ("2_3", (xusd::bind(&MyTest::to_string, &test, _1, _2, _3)("", "_", "")));
EXPECT_EQ("", (xusd::bind(&MyTest::to_string, &test, _2, _3, _1)("", "", "")));
EXPECT_EQ("", (xusd::bind(&MyTest::to_string, &test, _3, _1, _2)("", "", ""))); EXPECT_EQ("", (xusd::bind(&MyTest::to_string, _4, _3, _1, _2)("", "", "", &test))); xusd::bind(&MyTest::voidfun, &test)();
EXPECT_EQ(, g_test_voidfun); xusd::bind(&MyTest::constfun, &test)();
EXPECT_EQ(, g_test_voidfun);
} TEST(TestBind, TestFuncter){
using namespace xusd;
TestAddFuncter f1;
EXPECT_EQ(, (xusd::bind(f1, _1, _2)(, )));
} TEST(TestBind, TestCFunction){
using namespace xusd;
EXPECT_EQ(, (xusd::bind(abs, _1)(-)));
} TEST(TestBind, TestMemberObj){
MyTest t1;
EXPECT_EQ(t1.memObj, );
xusd::bind(&MyTest::memObj, &t1)() = ;
EXPECT_EQ(t1.memObj, );
} int main(int argc, char* argv[]){ ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
} namespace xusd{
placeholder<> _1;
placeholder<> _2;
placeholder<> _3;
placeholder<> _4;
placeholder<> _5;
placeholder<> _6;
placeholder<> _7;
placeholder<> _8;
placeholder<> _9;
placeholder<> _10;
placeholder<> _11;
placeholder<> _12;
placeholder<> _13;
placeholder<> _14;
placeholder<> _15;
placeholder<> _16;
placeholder<> _17;
placeholder<> _18;
placeholder<> _19;
placeholder<> _20;
placeholder<> _21;
placeholder<> _22;
placeholder<> _23;
placeholder<> _24;
}

山寨一个std::bind\boost::bind的更多相关文章

  1. boost::bind的简单实现

    前言 在上一篇blog中简单的实现了boost::function,支持带有2个参数的函数/函数指针,函数对象,函数适配器/bind类,以及带有1个参数的成员函数指针. 本文接着来介绍如何实现一个简单 ...

  2. boost::bind

    bind并不是一个单独的类或函数,而是非常庞大的家族,依据绑定的参数个数和要绑定的调用对象类型,总共有十个不同的形式,但它们的名字都叫bind. bind接受的第一个参数必须是一个可调用对象f,包括函 ...

  3. boost::bind 和 boost::function 基本用法

    这是一篇介绍bind和function用法的文章,起因是近来读陈硕的文章,提到用bind和function替代继承,于是就熟悉了下bind和function的用法,都是一些网上都有的知识,记录一下,期 ...

  4. 以boost::function和boost:bind取代虚函数

    转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...

  5. (转)boost::bind介绍

    转自:http://www.cnblogs.com/sld666666/archive/2010/12/14/1905980.html 这篇文章介绍boost::bind()的用法, 文章的主要内容是 ...

  6. 关于boost::function与boost::bind函数的使用心得

    最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...

  7. [转] [翻译]图解boost::bind

    http://kelvinh.github.io/blog/2013/12/03/boost-bind-illustrated/ 其实这是很久之前留的一个坑了,一直没有填.. 记得在刚开始看到 boo ...

  8. 使用BOOST BIND库提高C++程序性能

    Boost.Bind为函数和函数对象,值语义和指针提供语义了一致的语法.我们首先通过一些简单的例子来看看它的基本用法,之后我们会延伸到嵌套绑定以实现功能组合.理解bind用法的一个关键是理解占位符(p ...

  9. boost::bind的使用方法

    bind - boost 头文件: boost/bind.hpp bind 是一组重载的函数模板.用来向一个函数(或函数对象)绑定某些参数. bind的返回值是一个函数对象. 它的源文件太长了. 看不 ...

随机推荐

  1. 虚拟机里面做了个MySQLS主从:

    虚拟机里面做了个主从: 但是IO现成一直不能跟主库上的dump现成通信, Slave_IO_Running: No Last_IO_Error: error connecting to master ...

  2. iOS调试证书/公布证书制作

    当已经注冊过applied 开发人员账号后,而且进行付款了,那么接下来就是证书制作了 1.登录membercenter https://developer.apple.com/membercenter ...

  3. HDU Always Cook Mushroom (极角排序+树状数组)

    Problem Description Matt has a company, Always Cook Mushroom (ACM), which produces high-quality mush ...

  4. 19、Java访问修饰符

    修饰符 本类 同一个包中的类 子类 其它类 public 可以访问 可以访问 可以访问 可以访问 protected 可以访问 可以访问 可以访问 不能访问 默认 可以访问 可以访问 不能访问 不能访 ...

  5. Spring MVC Beginner’s Guide勘误表

    - 17 submitted: last submission 09 Dec 2016 Page number: 213 Qauntity should be: Quantity Page numbe ...

  6. C实现9种排序算法

    算法复杂度以及稳定性分析 算法名称 平均时间 辅助空间 稳定性 冒泡排序 O(n2) O(1) 是 选择排序 O(n2) O(1) 否 插入排序 O(n2) O(1) 是 自底向上归并排序 O(nlo ...

  7. PHP关于进程池的优化

    本文打算从另一个角度来讨论问题,教大家如何配置高效的环境,如此同样能够达到优化的目的. pool 一个让人沮丧的消息是绝大多数 PHP 程序员都忽视了池的价值.这里所说的池可不是指数据库连接池之类的东 ...

  8. Emacs 文件中的查找操作

    1,在本文件中查找 list-matching-lines 命令会列出本文件中所有出现text的地方.下面是它的一个输出示例: 7 matches for "ngx_http_wait_re ...

  9. MNIST数据集和IDX文件格式

    MNIST数据集 MNIST数据集是Yan Lecun整理出来的. NIST是美国国家标准与技术研究院(National Institute of Standards and Technology)的 ...

  10. React dva 的使用

    各大传送门: DvaJS Github DvaJS API与示例 了解 dva- dva = React-Router + Redux + Redux-saga + fetch - dva的初衷是(其 ...