文章分析怎样在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的更多相关文章

  1. html5高级

    Html5高级 项目回顾 Day 01 第三阶段知识体系: (1)AJAX异步请求 数据库.PHP.HTTP.原生AJAX.jQuery中的AJAX (2)HTML5高级特性 九大新特性 (3)Boo ...

  2. 读书笔记-JVM

    局部变量表(虚拟机栈中的一部分)在编译期完成分配,运行期不会再改变大小: 每个方法对应一个栈帧(存储局部变量表.操作数栈.动态链接.方法出口等),栈帧被存储到虚拟机栈中,每个线程对应一个虚拟机栈,方法 ...

  3. js 获取验证码计时器

    效果图: 贴上代码: <div class="logintitle"> <input type="tel" id="mobile&q ...

  4. vue使用技巧:Promise + async + await 解决组件间串行编程问题

    业务场景描述 大家都通过互联网投递过简历,比如在智联.58.猎聘等平台.投递心仪的职位前一般都需要前提创建一份简历,简历编辑界面常规的布局最上面是用户的个人基本信息,如姓名.性别.年龄.名族等,接着是 ...

  5. 【后台管理系统】—— Ant Design Pro组件使用(二)

    一.关联表单项 - 动态增删输入框Input        封装子组件 class ParamsInputArray extends React.Component{ constructor(prop ...

  6. Element Form表单实践(上)

    作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...

  7. 地区sql

    /*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...

  8. c++11模拟boost元占位符placeholder

    准备实现meta programming的fold函数,发现自己缺少占位符实现,这样传入fold的transform op类(元函数)都不得不另外写个外覆类,其实我觉得没啥不好,简单直接,说实话干扰什 ...

  9. placeholder不兼容 IE10 以下版本的解决方法

    对于密码输入框placeholder的兼容问题:HTML代码:<input type="password" id="loginPassword" plac ...

随机推荐

  1. J2msi 自己制作的把exe打成安装包简易GUI程序

    因为wix是用命令行执行的,操作比较麻烦,所以自己写了个wix生成安装包的图形操作程序, 原理很简单,主要用java 来执行 wix 的heat .candle 和 light 命令 ,最后生成安装文 ...

  2. Flex 转载

  3. ssh-agent && 及 ssh-add介绍

    ssh-agent命令是一种控制用来保存公钥身份验证所使用的私钥的程序.ssh-agent在X会话或登录会话之初启动,所有其他窗口或程序则以客户端程序的身份启动并加入到ssh-agent程序中.通过使 ...

  4. PLSQL乱码&TNS-12557: protocol adapter not loadable解决

    PLSQL乱码&TNS-12557: protocol adapter not loadable解决 PLSQL乱码&TNS-12557: protocol adapter not l ...

  5. 终结者:借助pinyin4j相关jar包提取汉字的首字母

    import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCase ...

  6. Windows 7 系统的旧版IE浏览器升级到IE11

    Windows 7 系统的旧版IE浏览器升级到IE11 2016年1月12日微软全面停止对IE8.IE9.IE10浏览器的支持,不再提供安全服务,如果继续使用将会造成安全隐患,因此 Windows 7 ...

  7. funuiTitle-居中问题修改

    今天遇到了一个问题,在一个actionbar上,title居中了,现在想要的方式是,让actionbar上显示返回按钮,后面紧跟着title.当时自己一直尝试要找到activity,然后在theme中 ...

  8. 2.技巧: 用 JAXM 发送和接收 SOAP 消息—Java API 使许多手工生成和发送消息方面必需的步骤自动化

    转自:https://www.cnblogs.com/chenying99/archive/2013/05/23/3094128.html 技巧: 用 JAXM 发送和接收 SOAP 消息—Java ...

  9. JS怎么判断数组类型?

    1.判断对象的constructor是否指向Array,接着判断特殊的属性length,splice等.[应用的是constructor的定义:返回对象所对应的构造函数.] eg: [].constr ...

  10. 微信小程序实现一个简单的表格

    wxml <view class="table"> <view class="tr bg-w"> <view class=&quo ...