本文实现以下功能,在VS2013上编译通过 (VS2012编译不过)
struct MyProcesser
{
template<int Index /*编译期索引值*/, int Count, typename T>
static // <-static是可选的
inline void process(const T& t)
{
std::cout << "■index:"<< Index << " type:" << typeid(t).name() << " value:" << t << "■"<<std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TupleForEach::foreach<MyProcesser>(std::make_tuple("0", std::string("str"), 2.0, 3), &MyProcesser());
TupleForEach::foreach_reverse<MyProcesser>(std::make_tuple("0", std::string("str"), 2.0, 3));
// GetNumbers<5>::Tuple tuple_Of_Numbers5; //tuple<Number<0>,Number<1>, ... Number<4>>
// GetNumbers<3>::type Numbers0to2; //Numbers<0,1,2>
return 0;
}
支持代码(可以放头文件)
#include <tuple>
struct _NumbersHelper
{
// SNumber<4> 这样的类,把编译期int常量包装成类
template<int N>
struct SNumber
{
enum { value = N };
};
// SNumbers<0,1,2,3,4,5,6> 这样的类
template<int... Args>
class SNumbers
{
};
// GetTupleOfNumbers(std::tuple<>, 数字的个数) -> std::tuple<SNumber<0>, SNumber<1> , ... SNumber<Count-1> >
template <typename Tuple, int Count, class = std::enable_if<(std::tuple_size<Tuple>::value == Count)>::type >
static auto GetTupleOfNumbers() -> Tuple;
template <typename Tuple, int Count, class = std::enable_if<(std::tuple_size<Tuple>::value < Count)>::type >
static auto GetTupleOfNumbers()-> decltype(GetTupleOfNumbers<typename std::_Tuple_cat1<Tuple, std::tuple<SNumber<std::tuple_size<Tuple>::value>>>::type, Count>());
// GetNumberFromTuple(std::tuple<SNumber<0>, SNumber<1>, ... >) -> SNumbers<0, 1, ...>
template<typename... Args>
static auto GetNumberFromTuple(std::tuple<Args...>*)->SNumbers < Args::value ... > ;
// GetNumbers<Count>::type -> SNumber<0, 1, 2, ..., Count-1>
template<int Count>
struct GetNumbers
{
typedef decltype(GetTupleOfNumbers<std::tuple<>, Count>()) Tuple;
typedef decltype(GetNumberFromTuple((Tuple*)0)) type;
};
};
namespace TupleForEach
{
//内循环,根据索引进行调用Processer的process函数,兼容static
template <typename Processer, typename Tuple, int... Indexes>
inline void _foreach(Tuple& values, _NumbersHelper::SNumbers<Indexes...>*, Processer* p = NULL)
{
enum { TupleSize = std::tuple_size<Tuple>::value };
bool n[] = { (p->process<Indexes, TupleSize>(std::get<Indexes>(values)), false)... };
}
//外嵌套用于把索引展开
template <typename Processer, typename Tuple>
inline void foreach(Tuple& values, Processer* p = NULL)
{
enum { TupleSize = std::tuple_size<Tuple>::value };
return _foreach<Processer>(values, (_NumbersHelper::GetNumbers<TupleSize>::type*)0, p);
}
//内循环,根据索引进行调用Processer的process函数,兼容static
template <typename Processer, typename Tuple, int... Indexes>
inline void _foreach_reverse(Tuple& values, _NumbersHelper::SNumbers<Indexes...>*, Processer* p = NULL)
{
enum { TupleSize = std::tuple_size<Tuple>::value };
bool n[] = { (p->process<TupleSize - Indexes - 1, TupleSize>(std::get<TupleSize - Indexes - 1>(values)), false)... };
}
//外嵌套用于把索引展开
template <typename Processer, typename Tuple>
inline void foreach_reverse(Tuple& values, Processer* p = NULL)
{
enum { TupleSize = std::tuple_size<Tuple>::value };
return _foreach_reverse<Processer>(values, (_NumbersHelper::GetNumbers<TupleSize>::type*)0, p);
}
}