zoukankan      html  css  js  c++  java
  • 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;
    }



  • 相关阅读:
    vue中打印 使用mapState映射 vuex state 中的数据 结果显示 [__ob__: Observer]的问题
    css里面鼠标的形状-----》easyui哪点事
    多张表进行关联查询---->删除某个数据的时候出现还有子记录的提示
    MyEclipse迁移过程中Tomcat版本不一致的解决办法
    Easyui里面动态设置输入框的可见性
    PL/SQL那点事-->修改Oracle数据库里面的字段长度
    PL/SQL那点事-->SqlSession operation; SQL []; ORA-01722: 无效数字
    PL/SQL数据开发那点事
    PL/SQL数据库开发那点事
    java类型与jdbc类型对应表
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7007692.html
Copyright © 2011-2022 走看看