C++11实现placeholder
文章分析怎样在C++11中实现简单的placeholder。
首先看看什么是placeholder:
for_each(arr.begin(), arr.end(), cerr << _0 << endl);
当中arr的类型是vector<int>,第三个參数是一个表达式,表达式中有一个操作数是_0。第三个參数含义是对这个表达式进行求值,得到一个对象x,x拥有operator ()(int a)的成员函数。整个表达式意味着把arr的每个元素b取出来。然后调用x(b)。而x(b)的效果是将b输出到一行当中。当中的_0就是placeholder,在表达式中作为一个占位符存在,等待外部给出_0的类型和值的时候,整个表达式再求值。
这是个非常酷的语法糖。在C++11中能够用lambda表达式取代,只是弄明确怎么实现对于模板元编程的能力会有所提升。以下来分析一下怎样去实现placeholder:
考虑_0, _1这些占位符,首先搞明确它们在C++中的语法成份。出如今表达式中,并且表达式不是处于某个模板的环境。能够肯定在编译时能知道表达式的全部操作数的类型。
_0能够是一个形如被定义为make_placeholder0()的宏。也能够是T0 _0;之类的一个对象。只是这没有关系,我们仅仅关心_0这个表达式的类型。能够看出_0应该具有类类型。operator << 能作用于该类型的对象上。
占位符和其他操作数进行运算,会产生新的类型,新的类型还能够參加运算,最后使得cerr << _0 << endl这个表达式具有某个类型。我们假定这个产生的新的类型是TExpr。TExpr在运算后仍然是TExpr类型。假设把语法树的结点用类型标注一下,对于表达式_0 + _1 -
_2应该是例如以下结果
- : TExpr
+ : TExpr _2 : T2
_0 : T0 _1 : T1
TExpr将拥有operator ()。可以求值。可是眼下看来TExpr上的operator () 具有不确定性:
根结点上,operator将使用两个操作数。把减法操作应用在两个操作数上。
在左边的结点上,是将加法应用在两个操作数上。
所以TExpr中的operator ()是多态的。
假设将语法树改为:
- : TExpr<MinusTag>
+ : TExpr<AddTag> _2 : T2
_0 : T0 _1 : T1
事情就变得easy一些,TExpr是參数化的,依据不同的Tag參数,在operator ()时有不同的行为。
能够预见我们应该构造一堆这种类:
template<typename L, typename R, typename T>
class TExpr; template<typename L, typename R>
class TExpr<L, R, AddTag>
{
L left_operand;
R right_operand;
}; template<typename L, typename R>
class TExpr<L, R, SubTag>
{
L left_operand;
R right_operand;
};
当中L,R两个类型可能是T0。T1等占位符的类型,或者是TExpr<,,,>,或者是其他类型。可是这样做有个缺点。把參数个数写死了。于是将上面的AddTag和TExpr组合到一起,形成
template<typename T1, typename T2>
struct TExprAdd
{
};
template<typename T1, typename T2>
struct TExprSub
{
};
进一步,将_0和_1的类型定义为:
template<int v>
struct TExprBasic
{
};
并提供操作:
template<typename T1, typename T2>
TExprAdd<T1, T2>
operator + (T1 a, T2 b)
{
typedef TExprAdd<T1, T2> TI;
return TI(a, b);
} template<typename T1, typename T2>
TExprSub<T1, T2>
operator - (T1 a, T2 b)
{
typedef TExprSub<T1, T2> TI;
return TI(a, b);
}
于是语法树变为:
- : TExprSub<TExprAdd<TExprBasic<0>, TExprBasic<1>>, TExprBasic<2>>
+ : TExprAdd<TExprBasic<0>, TExprBasic<1>> _2 : TExprBasic<2>
_0 : TExprBasic<0> _1 : TExprBasic<1>
至此,我们已经给出了一个能够用的placeholder的架构了。
我们要求TExprAdd,TExprSub拥有一些共性,满足某个concept,这个concept就是TExpr。这个concept是自己在编程中心中默默建立的。当然也能够把这个concept用显式的方式写出来:
<pre name="code" class="cpp">template<typename T>
class TExpr
{
// require 1:T具有计算返回类型的元函数get_result_type
template<typename TUPLE>
struct get_result_type
{
typedef typename T::template get_result_type<TUPLE> Impl;
typedef typename Impl::result_type result_type;
}; // require 2:T的对象应该具有operator () 成员函数模板,用于求值
template<typename... Arg>
auto operator () (Arg... arg)->typename get_result_type<std::tuple<Arg...>>::result_type
{
return impl.template operator () (std::forward<std::tuple<TL...>>(t));
} T impl;
}; template<typename T1, typename T2>
TExpr<TExprAdd<T1, T2> >
operator + (T1 a, T2 b)
{
typedef TExprAdd<T1, T2> TI;
return TExpr<TI>(TI(a, b));
} template<typename T1, typename T2>
TExpr<TExprSub<T1, T2> >
operator - (T1 a, T2 b)
{
typedef TExprSub<T1, T2> TI;
return TExpr<TI>(TI(a, b));
}
这样就相当于描写叙述了一个TExpr接口,有若干个详细实现:TExprBasic。TExprAdd,TExprSub等。[在这里接口的描写叙述体如今TExpr对模板參数类型的依赖。要求T包括什么样的类型,要求T的对象有什么样的操作。接口的实现体如今把TExpr<...>作为TExpr的模板參数。]嗯。也就是表达式模板技术。
于是我们的语法树中的-和+结点的类型分别变为:
TExpr<TExprAdd<TExprBasic<0>, TExprBasic<1>>>和TExpr<TExprSub<TExprAdd<TExprBasic<0>, TExprBasic<1>>, TExprBasic<2>>>添加TExpr优点是,语法树中的结点被分为三类:TExpr<...>。TExprBasic<...>。以及其他。这三类结点要求可以计算返回类型,求值。
首先明白计算的输入和输出,返回类型的输入是变长模板參数,返回一个返回类型,求值的输入是tuple,返回一个值。而三种类型的编译时和执行时求值策略非常清楚:1.
TExpr能够直接依赖于模板參数。计算返回值类型,求值。2. TExprBasic能够直接计算返回值类型(输入变长模板參数,返回该模板參数某个位置上的类型),直接求值(输入tuple,返回tuple中某一项)。
3. 其他类型的计算返回值类型,求值方法就是本身的类型和值。
所以能够很easy地针对这三类结点写出处理类。另外还有TExprAdd之类的类没有处理。这类结点的返回值类型计算须要分别计算其左操作数和右操作数的类型,然而在C++11中我们能够方便地用decltype(TA()+TB())来进行处结果的类型推导。而求值也是分别计算左右操作数的值,然后中间填上一个相应的操作符,作为一个表达式返回。[另外。还能够把TExprBasic作为TExpr的參数,这样全部的结点类型仅仅剩下TExpr和其他类型了,更加方便管理。这个包装过程仅仅须要改改代码就可以。
只是不改也能体现出一种思想,TExpr是递归的。TExprBasic是原子的,其他类型是原子的。]在此基础上,还引入两类print函数。没有參数的能输出带占位符的语法树。有參数的能输出带很多其他信息的语法树。
#include <iostream>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std; template<int v>
struct int_{enum{value=v};}; template<typename T>
struct value_of{enum{value=-1};}; template<int v>
struct value_of<int_<v>>{enum{value=v};}; template<typename V1, typename V2>
struct max_type
{
template<typename VA, typename VB, bool>
struct max_type_impl
{
typedef VA result_type;
};
template<typename VA, typename VB>
struct max_type_impl<VA, VB, true>
{
typedef VB result_type;
};
enum{value1=value_of<V1>::value, value2=value_of<V2>::value};
typedef typename max_type_impl<V1, V2, (value1<value2)>::result_type result_type;
}; template<typename T>
struct TExpr
{ TExpr(T o) : v(o){} template<typename TUPLE>
struct get_result_type
{
typedef typename T::template get_result_type<TUPLE> Impl;
typedef typename Impl::result_type result_type;
};
template<typename... Arg>
auto operator () (Arg... arg)->typename get_result_type<std::tuple<Arg...>>::result_type
{
return this->template evalue(std::tuple<Arg...>(arg...));
}
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)->typename get_result_type<std::tuple<TL...>>::result_type
{
return v.template evalue(std::forward<std::tuple<TL...>>(t));
}
template<typename... Arg>
void print(Arg... arg)
{
this->template print(tuple<Arg...>(arg...));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
v.template print(std::forward<std::tuple<TL...>>(t));
}
void print()
{
v.print();
}
T v;
}; template<int v>
struct TExprBasic
{
template<typename TUPLE>
struct get_result_type
{
typedef typename std::tuple_element<v, TUPLE>::type result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)->typename get_result_type<std::tuple<TL...>>::result_type
{
return std::get<v>(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
cout << std::get<v>(std::forward<std::tuple<TL...>>(t));
}
void print()
{
cout << v;
}
}; template<typename T>
struct is_expr
{
enum{value=false};
};
template<typename T>
struct is_expr<TExpr<T>>
{
enum{value=true};
};
template<int v>
struct is_expr<TExprBasic<v>>
{
enum{value=true};
}; template<typename T, typename TUPLE>
struct get_result_type
{
typedef T result_type;
};
template<typename T, typename TUPLE>
struct get_result_type<TExpr<T>, TUPLE>
{
typedef typename TExpr<T>::template get_result_type<TUPLE>::result_type result_type;
};
template<int v, typename TUPLE>
struct get_result_type<TExprBasic<v>, TUPLE>
{
typedef typename TExprBasic<v>::template get_result_type<TUPLE>::result_type result_type;
}; template<typename T>
struct print_helper_t
{
typedef int_<is_expr<T>::value> U; print_helper_t(T a) : x(a){} void print()
{
print_impl(U());
}
void print_impl(int_<1>)
{
x.print();
}
void print_impl(int_<0>)
{
cout << x;
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
print_impl(std::forward<std::tuple<TL...>>(t), U());
}
template<typename... TL>
void print_impl(std::tuple<TL...>&& t, int_<1>)
{
x.print(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print_impl(std::tuple<TL...>&& t, int_<0>)
{
cout << x;
}
T x;
};
template<typename T>
print_helper_t<T> print_helper(T x)
{
return print_helper_t<T>(x);
} template<typename T, typename TUPLE>
struct value_helper_t
{
typedef int_<is_expr<T>::value> U;
typedef typename ::get_result_type<T, TUPLE>::result_type result_type; value_helper_t(T a) : x(a){} template<typename... TL>
result_type value(std::tuple<TL...>&& t)
{
return value_impl(std::forward<std::tuple<TL...>>(t), U());
}
template<typename... TL>
result_type value_impl(std::tuple<TL...>&& t, int_<1>)
{
return x.template evalue(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
result_type value_impl(std::tuple<TL...>&& t, int_<0>)
{
return x;
}
T x;
};
template<typename T, typename TUPLE>
value_helper_t<T, TUPLE> value_helper(T x)
{
return value_helper_t<T, TUPLE>(x);
} template<typename T1, typename T2>
struct TExprAdd
{ TExprAdd(T1 a, T2 b) : x(a), y(b){} template<typename TUPLE>
struct get_result_type
{
typedef typename ::get_result_type<T1, TUPLE>::result_type TA;
typedef typename ::get_result_type<T2, TUPLE>::result_type TB;
typedef decltype(TA()+TB()) result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)-> typename get_result_type<std::tuple<TL...>>::result_type
{
return value_helper<T1, std::tuple<TL...>>(x).template value(std::forward<std::tuple<TL...>>(t)) +
value_helper<T2, std::tuple<TL...>>(y).template value(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
cout << "(";
print_helper(x).template print(std::forward<std::tuple<TL...>>(t));
cout << " + ";
print_helper(y).template print(std::forward<std::tuple<TL...>>(t));
cout << ")";
}
void print()
{
cout << "(";
print_helper(x).template print();
cout << " + ";
print_helper(y).template print();
cout << ")";
}
T1 x;
T2 y;
}; template<typename T1, typename T2>
struct TExprSub
{ TExprSub(T1 a, T2 b) : x(a), y(b){} template<typename TUPLE>
struct get_result_type
{
typedef typename ::get_result_type<T1, TUPLE>::result_type TA;
typedef typename ::get_result_type<T2, TUPLE>::result_type TB;
typedef decltype(TA()-TB()) result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)-> typename get_result_type<std::tuple<TL...>>::result_type
{
return value_helper<T1, std::tuple<TL...>>(x).template value(std::forward<std::tuple<TL...>>(t)) -
value_helper<T2, std::tuple<TL...>>(y).template value(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
cout << "(";
print_helper(x).template print(std::forward<std::tuple<TL...>>(t));
cout << " - ";
print_helper(y).template print(std::forward<std::tuple<TL...>>(t));
cout << ")";
}
void print()
{
cout << "(";
print_helper(x).template print();
cout << " - ";
print_helper(y).template print();
cout << ")";
}
T1 x;
T2 y;
}; template<typename T1, typename T2>
struct TExprMul
{ TExprMul(T1 a, T2 b) : x(a), y(b){} template<typename TUPLE>
struct get_result_type
{
typedef typename ::get_result_type<T1, TUPLE>::result_type TA;
typedef typename ::get_result_type<T2, TUPLE>::result_type TB;
typedef decltype(TA()*TB()) result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)-> typename get_result_type<std::tuple<TL...>>::result_type
{
return value_helper<T1, std::tuple<TL...>>(x).template value(std::forward<std::tuple<TL...>>(t)) *
value_helper<T2, std::tuple<TL...>>(y).template value(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
cout << "(";
print_helper(x).template print(std::forward<std::tuple<TL...>>(t));
cout << "*";
print_helper(y).template print(std::forward<std::tuple<TL...>>(t));
cout << ")";
}
void print()
{
cout << "(";
print_helper(x).template print();
cout << "*";
print_helper(y).template print();
cout << ")";
}
T1 x;
T2 y;
}; template<typename T1, typename T2>
struct TExprDiv
{ TExprDiv(T1 a, T2 b) : x(a), y(b){} template<typename TUPLE>
struct get_result_type
{
typedef typename ::get_result_type<T1, TUPLE>::result_type TA;
typedef typename ::get_result_type<T2, TUPLE>::result_type TB;
typedef decltype(TA()/TB()) result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)-> typename get_result_type<std::tuple<TL...>>::result_type
{
return value_helper<T1, std::tuple<TL...>>(x).template value(std::forward<std::tuple<TL...>>(t)) /
value_helper<T2, std::tuple<TL...>>(y).template value(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
cout << "(";
print_helper(x).template print(std::forward<std::tuple<TL...>>(t));
cout << "/";
print_helper(y).template print(std::forward<std::tuple<TL...>>(t));
cout << ")";
}
void print()
{
cout << "(";
print_helper(x).template print();
cout << "/";
print_helper(y).template print();
cout << ")";
}
T1 x;
T2 y;
}; template<typename T1, typename T2>
struct TExprComma
{ TExprComma(T1 a, T2 b) : x(a), y(b){} template<typename TUPLE>
struct get_result_type
{
typedef typename ::get_result_type<T1, TUPLE>::result_type TA;
typedef typename ::get_result_type<T2, TUPLE>::result_type TB;
typedef TB result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)-> typename get_result_type<std::tuple<TL...>>::result_type
{
value_helper<T1, std::tuple<TL...>>(x).template value(std::forward<std::tuple<TL...>>(t));
return value_helper<T2, std::tuple<TL...>>(y).template value(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
cout << "(";
print_helper(x).template print(std::forward<std::tuple<TL...>>(t));
cout << " , ";
print_helper(y).template print(std::forward<std::tuple<TL...>>(t));
cout << ")";
}
void print()
{
cout << "(";
print_helper(x).template print();
cout << " , ";
print_helper(y).template print();
cout << ")";
}
T1 x;
T2 y;
}; template<typename T1, typename T2>
struct TExprShiftLeft
{ TExprShiftLeft(T1 a, T2 b) : x(a), y(b){} template<typename TUPLE>
struct get_result_type
{
typedef typename ::get_result_type<T1, TUPLE>::result_type TA;
typedef typename ::get_result_type<T2, TUPLE>::result_type TB;
typedef TA result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)-> typename get_result_type<std::tuple<TL...>>::result_type
{
return value_helper<T1, tuple<TL...>>(x).template value(std::forward<std::tuple<TL...>>(t)) <<
value_helper<T2, tuple<TL...>>(y).template value(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
typedef typename get_result_type<tuple<TL...>>::result_type result_type;
output("(", int_<std::is_integral<result_type>::value>());
print_helper(x).template print(std::forward<std::tuple<TL...>>(t));
cout << " << ";
print_helper(y).template print(std::forward<std::tuple<TL...>>(t));
output(")", int_<std::is_integral<result_type>::value>());
}
void print()
{
//output("(", int_<std::is_integral<result_type>::value>());
print_helper(x).template print();
cout << " << ";
print_helper(y).template print();
//output(")", int_<std::is_integral<result_type>::value>());
}
void output(const char* s, int_<1>)
{
cout << s;
}
void output(const char* s, int_<0>)
{
}
T1 x;
T2 y;
}; template<typename T>
struct TExprShiftLeft<ostream, T>
{
TExprShiftLeft(ostream& a, T b) : x(a), y(b){} template<typename TUPLE>
struct get_result_type
{
typedef ostream& result_type;
};
template<typename... TL>
auto evalue(std::tuple<TL...>&& t)->typename get_result_type<std::tuple<TL...>>::result_type
{
return x << value_helper<T, tuple<TL...>>(y).template value(std::forward<std::tuple<TL...>>(t));
}
template<typename... TL>
void print(std::tuple<TL...>&& t)
{
cout << "cout << ";
y.print(std::forward<std::tuple<TL...>>(t));
}
void print()
{
cout << "xout << ";
y.print();
}
ostream& x;
T y;
}; template<typename T1, typename T2>
TExpr<TExprAdd<T1, T2> >
operator + (T1 a, T2 b)
{
typedef TExprAdd<T1, T2> TI;
return TExpr<TI>(TI(a, b));
} template<typename T1, typename T2>
TExpr<TExprSub<T1, T2> >
operator - (T1 a, T2 b)
{
typedef TExprSub<T1, T2> TI;
return TExpr<TI>(TI(a, b));
} template<typename T1, typename T2>
TExpr<TExprMul<T1, T2> >
operator * (T1 a, T2 b)
{
typedef TExprMul<T1, T2> TI;
return TExpr<TI>(TI(a, b));
} template<typename T1, typename T2>
TExpr<TExprDiv<T1, T2> >
operator / (T1 a, T2 b)
{
typedef TExprDiv<T1, T2> TI;
return TExpr<TI>(TI(a, b));
} template<typename T1, typename T2>
TExpr<TExprComma<T1, T2> >
operator , (T1 a, T2 b)
{
typedef TExprComma<T1, T2> TI;
return TExpr<TI>(TI(a, b));
} template<typename T>
TExpr<TExprShiftLeft<ostream, TExpr<T> > >
operator << (ostream& out, TExpr<T> x)
{
typedef TExprShiftLeft<ostream, TExpr<T>> TI;
return TExpr<TI>(TI(out, x));
} template<int T>
TExpr<TExprShiftLeft<ostream, TExprBasic<T> > >
operator << (ostream& out, TExprBasic<T> x)
{
typedef TExprShiftLeft<ostream, TExprBasic<T>> TI;
return TExpr<TI>(TI(out, x));
} template<typename T1, typename T2>
TExpr<TExprShiftLeft<TExpr<T1>, T2>>
operator << (TExpr<T1> e, T2 x)
{
typedef TExprShiftLeft<TExpr<T1>, T2> TI;
return TExpr<TI>(TI(e, x));
} template<int v, typename T1>
TExpr<TExprShiftLeft<TExprBasic<v>, T1>>
operator << (TExprBasic<v> e, T1 x)
{
typedef TExprShiftLeft<TExprBasic<v>, T1> TI;
return TExpr<TI>(TI(e, x));
} #define MAKE(x) TExprBasic<x> _ ## x
MAKE(0);MAKE(1);MAKE(2);MAKE(3);MAKE(4);MAKE(5);MAKE(6);MAKE(7);MAKE(8);MAKE(9); int main()
{
auto add = _0 + _1;
cout << add(string("123"), "456") << endl;
cout << add((int*)0, 1) << endl;
cout << add("12345678", 1) << endl; auto test = (cerr << ((_0 << _1) + _2 * 0 - _1 / _2) << "___" << _3 << "___" << (int*)&main, cerr << _0, 1);
test.print();
cout << endl;
test.print(4, 5, 6, string("c++"));
cout << endl << "=";
test(4, 5, 6, "hello world");
cout << endl; int init = 0;
vector<int> vec(8);
for_each(vec.begin(), vec.end(), [&](int& a){a=++init;});
for_each(vec.begin(), vec.end(), cout << _0);
return 0;
}
C++11实现placeholder的更多相关文章
- html5高级
Html5高级 项目回顾 Day 01 第三阶段知识体系: (1)AJAX异步请求 数据库.PHP.HTTP.原生AJAX.jQuery中的AJAX (2)HTML5高级特性 九大新特性 (3)Boo ...
- 读书笔记-JVM
局部变量表(虚拟机栈中的一部分)在编译期完成分配,运行期不会再改变大小: 每个方法对应一个栈帧(存储局部变量表.操作数栈.动态链接.方法出口等),栈帧被存储到虚拟机栈中,每个线程对应一个虚拟机栈,方法 ...
- js 获取验证码计时器
效果图: 贴上代码: <div class="logintitle"> <input type="tel" id="mobile&q ...
- vue使用技巧:Promise + async + await 解决组件间串行编程问题
业务场景描述 大家都通过互联网投递过简历,比如在智联.58.猎聘等平台.投递心仪的职位前一般都需要前提创建一份简历,简历编辑界面常规的布局最上面是用户的个人基本信息,如姓名.性别.年龄.名族等,接着是 ...
- 【后台管理系统】—— Ant Design Pro组件使用(二)
一.关联表单项 - 动态增删输入框Input 封装子组件 class ParamsInputArray extends React.Component{ constructor(prop ...
- Element Form表单实践(上)
作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...
- 地区sql
/*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...
- c++11模拟boost元占位符placeholder
准备实现meta programming的fold函数,发现自己缺少占位符实现,这样传入fold的transform op类(元函数)都不得不另外写个外覆类,其实我觉得没啥不好,简单直接,说实话干扰什 ...
- placeholder不兼容 IE10 以下版本的解决方法
对于密码输入框placeholder的兼容问题:HTML代码:<input type="password" id="loginPassword" plac ...
随机推荐
- AC自动机 hdu2222
#include <iostream> using namespace std; struct Node{ Node *next[]; Node* fail; int count; Nod ...
- 【Cocos2d-x 017】 多分辨率适配全然解析
转:http://blog.csdn.net/w18767104183/article/details/22668739 文件夹从Cocos2d-x 2.0.4開始,Cocos2d-x提出了自己的多分 ...
- 【原创】k8s源代码分析-----EndpointController
转自本人空间 http://user.qzone.qq.com/29185807/blog/1459325937 一.controller manager创建endpointController 代码 ...
- 简单的横向ListView实现(version 3.0)
版本号2仅仅是简单的实现了当手指按下的时候listView的Item向左移动一定的距离,并没有随着手指的左右移动而左右滚动.在这个版本号3.0中将会实现随着手指的移动而滚动的目标:当手指向左移动的时候 ...
- 细说 iOS 消息推送
APNS的推送机制 与Android上我们自己实现的推送服务不一样,Apple对设备的控制很严格.消息推送的流程必需要经过APNs: 这里 Provider 是指某个应用的Developer,当然假设 ...
- 利用淘宝ip库限制地区访问
https://sss.one/97.html 利用淘宝ip库限制地区访问 有些应用可能需要对某些地区的用户进行限制访问 在采用才此方法的时候,可以利用一些ip库对访问者的ip进行判断 淘宝ip库地址 ...
- 删除D盘空目录 、检索大于10M的文件
删除D盘空目录 @echo off for %%i in (d:\xx) do ( if exist %%i:\ ( for /f "delims=" %%a in ('dir / ...
- WIN8.1的安装和打开"这台电脑"速度很慢的解决办法
WIN8.1的安装和打开"这台电脑"速度很慢的解决办法 对于非服务器用的电脑,如果电脑的内存在2G或更高,首推的操作系统是 WINDOWS8.1 64位企业版,用了就知道,没有比这流畅懂事的操作系统. ...
- php资源类型变量
php资源类型变量 一.总结 1. php资源类型变量:用来打开文件.数据库连接.图形画布区域等的一种特殊变量,比如FILE *fp; 二.PHP: Resource 资源类型 Resource 资 ...
- php函数按地址传递参数(php引用)
php函数按地址传递参数(php引用) 一.总结 1.php引用:php引用和c++一样,都是在变量前加&(取地址符号) 2.php函数按地址传递参数:php函数按地址传递参数(php引用)也 ...