那么在fold_s内当调用push_back::apply时,显然push_back必须要具备从参数列表中挑选指定参数的能力,自然的,这个任务交给_1,_2占位符了。实现的办法你可以去查看boost mpl库的做法,也可使用我下边的做法(需要c++11支持):
#ifndef HI_MPL_PLACEHOLDERS_H_INCLUDED
#define HI_MPL_PLACEHOLDERS_H_INCLUDED
//////////////////////////////////////////////////////////////////////
namespace hi { namespace mpl {
//surport palceholders is too painful
namespace placeholders
{
namespace helper
{
template<typename... TList> struct arglist { };
typedef arglist<> nullargs;
template<unsigned int N, typename... TList> struct at;
template<unsigned int N, typename T, typename... TList>
struct at< N, arglist<T, TList...> >
{
typedef typename at< N - 1, arglist<TList...> >::type type;
};
template<typename T, typename... TList>
struct at< 0, arglist<T, TList...> >
{
typedef T type;
};
} // end of placeholders::helper
template<int n> struct Arg
{
template<typename ... TList>
struct apply
{
using type = typename helper::at<n - 1, helper::arglist<TList...> >::type;
};
private:
};
using _1 = Arg<1>;
using _2 = Arg<2>;
using _3 = Arg<3>;
using _4 = Arg<4>;
} // end of placeholders
}
}
#endif
  如上,_1::apply<int, char, float>::type为int,  _2::apply<int, char, float>::type为char。
  以上要注意的arglist是从0开始索引的,而外部Arg是从1开始索引的。
  至此让我们把push_back<_1, _2>完成:
template<>
struct push_back< _1, _2 >
{
template<typename... TList>
struct apply
{
using type = typename push_back<
typename _1::apply<TList...>::type,
typename _2::apply<TList...>::type>::type;
};
};
  fold_s把固定的一堆参数传入时,push_back总能挑选到正确位置的参数。下面我们来看看一个奇妙的改变,这将会让你恍然大悟_1, _2占位符的设计和来历。
  让我们把上面的代码中所有_1,_2的地方全部调换位置,得到一个新的特化:
template<>
struct push_back< _2, _1 >
{
template<typename... TList>
struct apply
{
using type = typename push_back<
typename _2::apply<TList...>::type,
typename _1::apply<TList...>::type>::type;
};
};
  使用这个新特化时,fold_s传入的第二个参数将被放到push_back的第一个参数位置,而_2位于push_back第一个参数的样子正好很形象的描述了这个行为。
  现在你明白了吧,push_back<_1,_2>和push_back<_2,_1>这2个特化组合在一起,让我们有了能够指称第一,第二个参数的能力。