Skip to content

Instantly share code, notes, and snippets.

@FrankHB
Last active December 23, 2015 19:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save FrankHB/6683890 to your computer and use it in GitHub Desktop.
Save FrankHB/6683890 to your computer and use it in GitHub Desktop.
//#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;
}
/*
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