Metaprogramming: integrate the new facilities into the library
This commit is contained in:
parent
7296e60731
commit
636ab6e608
3 changed files with 83 additions and 77 deletions
|
|
@ -93,81 +93,8 @@ fun2 ()
|
|||
using lib::meta::IndexSeq;
|
||||
using lib::meta::BuildIndexSeq;
|
||||
using lib::meta::BuildIdxIter;
|
||||
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* @internal pick a single argument from a variadic parameter pack
|
||||
* @tparam i the index number (zero based) of the argument to select
|
||||
* @warning i must be smaller than the number of arguments available
|
||||
*/
|
||||
template<size_t i>
|
||||
struct SelectVararg
|
||||
{
|
||||
template<typename ARG, typename...ARGS>
|
||||
static auto
|
||||
get (ARG, ARGS&& ...args)
|
||||
{
|
||||
return SelectVararg<i-1>::get (std::forward<ARGS> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SelectVararg<0>
|
||||
{
|
||||
template<typename ARG, typename...ARGS>
|
||||
static auto
|
||||
get (ARG&& a, ARGS...)
|
||||
{
|
||||
return std::forward<ARG>(a);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to single out one argument from a variadic argument pack.
|
||||
* @tparam idx the index number (zero based) of the argument to select
|
||||
* @remark typically this function is used "driven" by an likewise variadic index sequence,
|
||||
* where the index sequence itself is picked up by a pattern match; this usage pattern
|
||||
* allows arbitrarily to handle some of the arguments of a variable argument list,
|
||||
* as determined by the index sequence passed in.
|
||||
*/
|
||||
template<size_t idx, typename...ARGS>
|
||||
constexpr inline auto
|
||||
pickArg (ARGS&&... args)
|
||||
{
|
||||
static_assert (idx < sizeof...(args), "insufficient number of arguments");
|
||||
|
||||
return SelectVararg<idx>::get (std::forward<ARGS> (args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to pick one initialisation argument from a variadic argument pack,
|
||||
* falling back to a default constructed element of type `DEFAULT` in case of
|
||||
* insufficient number of variadic arguments.
|
||||
* @tparam idx the index number (zero based) of the argument to select
|
||||
* @tparam DEFALUT type of the default element to construct as fallback
|
||||
*/
|
||||
template<size_t idx, typename DEFAULT, typename...ARGS>
|
||||
constexpr inline auto
|
||||
pickInit (ARGS&&... args)
|
||||
{
|
||||
enum{
|
||||
SIZ = sizeof...(args),
|
||||
IDX = idx < SIZ? idx : 0
|
||||
};
|
||||
|
||||
return (idx < SIZ)? SelectVararg<IDX>::get (std::forward<ARGS> (args)...)
|
||||
: DEFAULT{};
|
||||
}
|
||||
|
||||
template<size_t, typename DEFAULT>
|
||||
constexpr inline DEFAULT
|
||||
pickInit ()
|
||||
{
|
||||
return DEFAULT{};
|
||||
}
|
||||
using lib::meta::pickArg;
|
||||
using lib::meta::pickInit;
|
||||
|
||||
|
||||
using Arr = std::array<int, 3>;
|
||||
|
|
|
|||
|
|
@ -245,5 +245,83 @@ namespace meta {
|
|||
|
||||
|
||||
|
||||
/* ==== Manipulation of variadic arguments ==== **/
|
||||
|
||||
namespace { // Implementation delegate template...
|
||||
/**
|
||||
* @internal pick a single argument from a variadic parameter pack
|
||||
* @tparam i the index number (zero based) of the argument to select
|
||||
* @warning i must be smaller than the number of arguments available
|
||||
*/
|
||||
template<size_t i>
|
||||
struct SelectVararg
|
||||
{
|
||||
template<typename ARG, typename...ARGS>
|
||||
static auto
|
||||
get (ARG, ARGS&& ...args)
|
||||
{
|
||||
return SelectVararg<i-1>::get (std::forward<ARGS> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SelectVararg<0>
|
||||
{
|
||||
template<typename ARG, typename...ARGS>
|
||||
static auto
|
||||
get (ARG&& a, ARGS...)
|
||||
{
|
||||
return std::forward<ARG>(a);
|
||||
}
|
||||
};
|
||||
}//(End)Implementation
|
||||
|
||||
|
||||
/**
|
||||
* Helper to single out one argument from a variadic argument pack.
|
||||
* @tparam idx the index number (zero based) of the argument to select
|
||||
* @remark typically this function is used "driven" by an likewise variadic index sequence,
|
||||
* where the index sequence itself is picked up by a pattern match; this usage pattern
|
||||
* allows arbitrarily to handle some of the arguments of a variable argument list,
|
||||
* as determined by the index sequence passed in.
|
||||
*/
|
||||
template<size_t idx, typename...ARGS>
|
||||
constexpr inline auto
|
||||
pickArg (ARGS&&... args)
|
||||
{
|
||||
static_assert (idx < sizeof...(args), "insufficient number of arguments");
|
||||
|
||||
return SelectVararg<idx>::get (std::forward<ARGS> (args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to pick one initialisation argument from a variadic argument pack,
|
||||
* falling back to a default constructed element of type `DEFAULT` in case of
|
||||
* insufficient number of variadic arguments.
|
||||
* @tparam idx the index number (zero based) of the argument to select
|
||||
* @tparam DEFALUT type of the default element to construct as fallback
|
||||
*/
|
||||
template<size_t idx, typename DEFAULT, typename...ARGS>
|
||||
constexpr inline auto
|
||||
pickInit (ARGS&&... args)
|
||||
{
|
||||
enum{
|
||||
SIZ = sizeof...(args),
|
||||
IDX = idx < SIZ? idx : 0
|
||||
};
|
||||
|
||||
return (idx < SIZ)? SelectVararg<IDX>::get (std::forward<ARGS> (args)...)
|
||||
: DEFAULT{};
|
||||
}
|
||||
|
||||
template<size_t, typename DEFAULT>
|
||||
constexpr inline DEFAULT
|
||||
pickInit ()
|
||||
{
|
||||
return DEFAULT{};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace lib::meta
|
||||
#endif /*LIB_META_VARIADIC_HELPER_H*/
|
||||
|
|
|
|||
|
|
@ -182,8 +182,9 @@ namespace test {
|
|||
CHECK (n1 == pickArg<0> (n1,n2,n3));
|
||||
CHECK (n2 == pickArg<1> (n1,n2,n3));
|
||||
CHECK (n3 == pickArg<2> (n1,n2,n3));
|
||||
|
||||
pickArg<3> (n1,n2,n3);
|
||||
|
||||
// does not compile...
|
||||
// pickArg<3> (n1,n2,n3);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue