Last active
December 23, 2015 19:39
-
-
Save FrankHB/6683890 to your computer and use it in GitHub Desktop.
20130924-01
ref:
http://tieba.baidu.com/p/2613668761
https://bitbucket.org/FrankHB/yslib
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#include <ystdex/variadic.hpp> // uncommitted, see file attached; | |
//#include <ystdex/type_op.hpp> // see YSLib/YBase::YStandardEx; | |
//#include <ystdex/functional.hpp> // ditto; | |
//#include <YSLib/Core/yevt.hpp> // for test; | |
//#include <YSLib/UI/ywidget.h> // ditto; | |
#include <YSLib/UI/ypanel.h> // all above included; | |
namespace ystdex | |
{ | |
template<typename... _types1, typename... _types2> | |
struct sequence_cat<std::tuple<_types1...>, std::tuple<_types2...>> | |
{ | |
using type = std::tuple<_types1..., _types2...>; | |
}; | |
template<size_t _vIdx, typename... _types> | |
struct sequence_element<_vIdx, std::tuple<_types...>> | |
: std::tuple_element<_vIdx, std::tuple<_types...>> | |
{}; | |
template<typename... _types, size_t... _vIdxSeq> | |
struct sequence_project<std::tuple<_types...>, variadic_sequence<_vIdxSeq...>> | |
{ | |
using type = std::tuple< | |
typename std::tuple_element<_vIdxSeq, std::tuple<_types...>>::type...>; | |
}; | |
template<typename... _types> | |
struct sequence_reverse<std::tuple<_types...>> | |
{ | |
private: | |
using tuple_type = std::tuple<_types...>; | |
public: | |
using type = sequence_project_t<tuple_type, sequence_reverse_t< | |
make_natural_sequence_t<std::tuple_size<tuple_type>::value>>>; | |
}; | |
using ystdex::variadic_sequence; | |
using ystdex::sequence_split_t; | |
using ystdex::sequence_cat_t; | |
using ystdex::sequence_element; | |
using ystdex::sequence_element_t; | |
using ystdex::sequence_project_t; | |
using ystdex::sequence_reverse_t; | |
using ystdex::make_natural_sequence_t; | |
using std::tuple; | |
using std::is_same; | |
// variadic_sequence<(sizeof...(_vSeq) - _vSeq - 1)...> | |
static_assert(sequence_element<1, variadic_sequence<1, 0, 3>>::value == 0, ""); | |
static_assert(is_same< | |
sequence_reverse_t<sequence_cat_t<variadic_sequence<1, 0, 3>, | |
variadic_sequence<4, 7, 2>>> | |
, | |
sequence_project_t<variadic_sequence<0, 1, 2, 3, 4, 7, 8>, | |
sequence_reverse_t<variadic_sequence<1, 0, 3, 4, 5, 2>>> | |
>::value, ""); | |
static_assert(is_same< | |
sequence_project_t<tuple<int, void, double, void>, | |
variadic_sequence<1, 0, 3>> | |
, | |
tuple<void, int, void> | |
>::value, ""); | |
static_assert(is_same< | |
sequence_reverse_t<tuple<int, void, void, float>> | |
, | |
tuple<float, void, void, int> | |
>::value, ""); | |
template<typename, class, class> | |
struct CallBase; | |
template<typename _tRet, typename... _tOrigParams, typename... _tParams, | |
size_t... _vSeq> | |
struct CallBase<_tRet(_tOrigParams...), tuple<_tParams...>, | |
ystdex::variadic_sequence<_vSeq...>> | |
{ | |
template<typename _fCallable> | |
static _tRet | |
Call(_fCallable&& f, tuple<_tOrigParams&&...>&& args, | |
ystdex::remove_reference_t<decltype(ystdex::decay_forward(f)( | |
yforward(std::get<_vSeq>(std::move(args)))...))>* = {}) | |
{ | |
ystdex::decay_forward(f)(yforward(std::get<_vSeq>(std::move(args)))...); | |
} | |
}; | |
template<typename, typename> | |
struct VProxy; | |
template<typename _tRet, typename... _tOrigParams> | |
struct VProxy<_tRet(_tOrigParams...), tuple<_tRet>> | |
: private CallBase<_tRet(_tOrigParams...), tuple<>, | |
ystdex::variadic_sequence<>> | |
{ | |
using CallBase<_tRet(_tOrigParams...), tuple<>, | |
ystdex::variadic_sequence<>>::Call; | |
}; | |
template<typename _tRet, typename... _tOrigParams, typename _tParam, | |
typename... _tParams> | |
struct VProxy<_tRet(_tOrigParams...), tuple<_tRet, _tParam, _tParams...>> | |
: private CallBase<_tRet(_tOrigParams...), | |
ystdex::sequence_reverse_t<tuple<_tParams..., _tParam>>, | |
ystdex::make_natural_sequence_t<sizeof...(_tParams) + 1>>, | |
private VProxy<_tRet(_tOrigParams...), tuple<_tRet, _tParams...>> | |
{ | |
using CallBase<_tRet(_tOrigParams...), | |
ystdex::sequence_reverse_t<tuple<_tParams..., _tParam>>, | |
ystdex::make_natural_sequence_t<sizeof...(_tParams) + 1>>::Call; | |
using VProxy<_tRet(_tOrigParams...), tuple<_tRet, _tParams...>>::Call; | |
}; | |
template<typename _tRet, typename... _tOrigParams, typename... _tParams> | |
struct VProxy<_tRet(_tOrigParams...), _tRet(_tParams...)> | |
: private VProxy<_tRet(_tOrigParams...), ystdex::sequence_cat_t< | |
tuple<_tRet>, ystdex::sequence_reverse_t<tuple<_tParams...>>>> | |
{ | |
using VProxy<_tRet(_tOrigParams...), sequence_cat_t<tuple<_tRet>, | |
sequence_reverse_t<tuple<_tParams...>>>>::Call; | |
}; | |
template<typename _fHandler, typename _fCallable> | |
struct VCaller | |
{ | |
_fCallable Callable; | |
template<typename _fCaller> | |
VCaller(_fCaller&& f) | |
: Callable(yforward(f)) | |
{} | |
template<typename... _tParams> | |
auto | |
operator()(_tParams&&... args) | |
-> decltype(VProxy<_fHandler, _fHandler>::Call(Callable, | |
forward_as_tuple(yforward(args)...))) | |
{ | |
return VProxy<_fHandler, _fHandler>::Call(Callable, | |
forward_as_tuple(yforward(args)...)); | |
} | |
}; | |
template<typename _fHandler, typename _fCallable> | |
yconstfn VCaller<_fHandler, _fCallable> | |
MakeVCaller(_fCallable&& f) | |
{ | |
return VCaller<_fHandler, _fCallable>(yforward(f)); | |
} | |
///xxx=MakeVCaller | |
int | |
main() | |
{ | |
using namespace YSLib; | |
using namespace UI; | |
using namespace std; | |
Panel pnl(Size(640, 480)); | |
GEvent<void(Panel&, double)> evt; | |
int z; | |
auto a = [&](IWidget&, short){z=1;printf("z=%d\n",z);}; | |
auto b = [&](Widget&){z=2;printf("z=%d\n",z);}; | |
evt += a; | |
evt += [=](Control& w, double){return b(w);}; | |
// evt += MakeVCaller([=](Control& w){return b(w);}); | |
auto vc = MakeVCaller<void(Panel&, int)>([=](Control& w){return b(w);});; | |
vc(pnl, 0); | |
// vc(pnl); // ill-formed; | |
// vc(); // ill-formed; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright by FrankHB 2013. | |
This file is part of the YSLib project, and may only be used, | |
modified, and distributed under the terms of the YSLib project | |
license, LICENSE.TXT. By continuing to use, modify, or distribute | |
this file you indicate that you have read the license and | |
understand and accept it fully. | |
*/ | |
/*! \file variadic.hpp | |
\ingroup YStandardEx | |
\brief C++ 变长参数相关操作。 | |
\version r232 | |
\author FrankHB <frankhb1989@gmail.com> | |
\since build 412 | |
\par 创建时间: | |
2013-06-06 11:38:15 +0800 | |
\par 修改时间: | |
2013-09-23 22:07 +0800 | |
\par 文本编码: | |
UTF-8 | |
\par 模块名称: | |
YStandardEx::Variadic | |
*/ | |
#ifndef YB_INC_ystdex_variadic_hpp_ | |
#define YB_INC_ystdex_variadic_hpp_ 1 | |
#include "../ydef.h" // for ystdex::size_t; | |
namespace ystdex | |
{ | |
/*! | |
\ingroup meta_types | |
\brief 变长参数标记的整数序列。 | |
\since build 303 | |
*/ | |
template<size_t... _vSeq> | |
struct variadic_sequence | |
{ | |
/*! | |
\brief 取序列长度。 | |
\note 同 C++1y std::integer_sequence::size 。 | |
\since build 447 | |
*/ | |
static yconstfn size_t | |
size() | |
{ | |
return sizeof...(_vSeq); | |
} | |
}; | |
/*! \defgroup vseq_operations Variadic Sequence Operations | |
\ingroup meta_operations | |
\brief 变长参数标记的序列相关的元操作。 | |
\since build 447 | |
形式为模板类名声明和特化的相关操作,被操作的序列是类类型。 | |
除此处对 ystdex::variadic_sequence 外的特化外,可有其它类类型的特化。 | |
特化至少需保证具有表示和此处特化意义相同的 type 类型成员。 | |
对于非类型元素,成员 value 表示结果,成员 type 表示对应的序列类型。 | |
*/ | |
/*! | |
\ingroup vseq_operations | |
\brief 拆分序列。 | |
\since build 447 | |
拆分序列为首元素和其余部分。 | |
*/ | |
//@{ | |
template<class> | |
struct sequence_split; | |
template<class _tSeq> | |
using sequence_split_t = typename sequence_split<_tSeq>::type; | |
template<size_t _vHead, size_t... _vTail> | |
struct sequence_split<variadic_sequence<_vHead, _vTail...>> | |
{ | |
static yconstexpr size_t value = _vHead; | |
using type = variadic_sequence<value>; | |
using tail = variadic_sequence<_vTail...>; | |
}; | |
//@} | |
/*! | |
\ingroup vseq_operations | |
\brief 合并序列。 | |
\since build 447 | |
*/ | |
//@{ | |
template<class, class> | |
struct sequence_cat; | |
template<class _tSeq1, class _tSeq2> | |
using sequence_cat_t = typename sequence_cat<_tSeq1, _tSeq2>::type; | |
template<size_t... _vSeq1, size_t... _vSeq2> | |
struct sequence_cat<variadic_sequence<_vSeq1...>, variadic_sequence<_vSeq2...>> | |
{ | |
using type = variadic_sequence<_vSeq1..., _vSeq2...>; | |
}; | |
//@} | |
/*! | |
\ingroup vseq_operations | |
\brief 取序列元素。 | |
\since build 447 | |
*/ | |
//@{ | |
template<size_t, class> | |
struct sequence_element; | |
template<size_t _vIdx, class _tSeq> | |
using sequence_element_t = typename sequence_element<_vIdx, _tSeq>::type; | |
template<size_t _vIdx> | |
struct sequence_element<_vIdx, variadic_sequence<>>; | |
template<size_t... _vSeq> | |
struct sequence_element<0, variadic_sequence<_vSeq...>> | |
{ | |
private: | |
using vseq = variadic_sequence<_vSeq...>; | |
public: | |
static yconstexpr auto value = sequence_split<vseq>::value; | |
using type = sequence_split_t<vseq>; | |
}; | |
template<size_t _vIdx, size_t... _vSeq> | |
struct sequence_element<_vIdx, variadic_sequence<_vSeq...>> | |
{ | |
private: | |
using sub = sequence_element<_vIdx - 1, | |
typename sequence_split<variadic_sequence<_vSeq...>>::tail>; | |
public: | |
static yconstexpr auto value = sub::value; | |
using type = typename sub::type; | |
}; | |
//@} | |
/*! | |
\ingroup vseq_operations | |
\brief 投影操作。 | |
\since build 447 | |
*/ | |
//@{ | |
template<class, class> | |
struct sequence_project; | |
template<class _tSeq, class _tIdxSeq> | |
using sequence_project_t = typename sequence_project<_tSeq, _tIdxSeq>::type; | |
template<size_t... _vSeq, size_t... _vIdxSeq> | |
struct sequence_project<variadic_sequence<_vSeq...>, | |
variadic_sequence<_vIdxSeq...>> | |
{ | |
using type = variadic_sequence< | |
sequence_element<_vIdxSeq, variadic_sequence<_vSeq...>>::value...>; | |
}; | |
//@} | |
/*! | |
\ingroup vseq_operations | |
\brief 取逆序列。 | |
\since build 447 | |
*/ | |
//@{ | |
template<class> | |
struct sequence_reverse; | |
template<class _tSeq> | |
using sequence_reverse_t = typename sequence_reverse<_tSeq>::type; | |
template<> | |
struct sequence_reverse<variadic_sequence<>> | |
{ | |
using type = variadic_sequence<>; | |
}; | |
template<size_t... _vSeq> | |
struct sequence_reverse<variadic_sequence<_vSeq...>> | |
{ | |
private: | |
using vseq = variadic_sequence<_vSeq...>; | |
public: | |
using type = sequence_cat_t<sequence_reverse_t<typename | |
sequence_split<vseq>::tail>, sequence_split_t<vseq>>; | |
}; | |
//@} | |
/*! | |
\ingroup meta_operations | |
\brief 取整数序列的自然数后继。 | |
\since build 303 | |
*/ | |
//@{ | |
template<class> | |
struct make_successor; | |
//! \since build 447 | |
template<class _tSeq> | |
using make_successor_t = typename make_successor<_tSeq>::type; | |
template<size_t... _vSeq> | |
struct make_successor<variadic_sequence<_vSeq...>> | |
{ | |
using type = variadic_sequence<_vSeq..., sizeof...(_vSeq)>; | |
}; | |
//@} | |
/*! | |
\ingroup meta_operations | |
\brief 取自然数变量标记序列。 | |
\since build 303 | |
*/ | |
//@{ | |
template<size_t> | |
struct make_natural_sequence; | |
//! \since build 447 | |
template<size_t _vN> | |
using make_natural_sequence_t = typename make_natural_sequence<_vN>::type; | |
template<size_t _vN> | |
struct make_natural_sequence | |
{ | |
using type = make_successor_t<make_natural_sequence_t<_vN - 1>>; | |
}; | |
template<> | |
struct make_natural_sequence<0> | |
{ | |
using type = variadic_sequence<>; | |
}; | |
//@} | |
} // namespace ystdex; | |
#endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment