c++ - Variadic template overload resolution -
suppose have list of template parameters can incremented. want increment head of list. here code
template<int n> struct counter { static constexpr counter<n+1> increment(); }; template<int n> constexpr counter<n+1> counter<n>::increment() { return counter<n+1>(); } //list (will used list of counters) template <typename... tail> struct list {}; template <typename head, typename... tail> struct list<head,tail...> {}; template <typename head, typename... tail> auto incrfront() -> decltype(list<decltype(head::increment()),tail...>()) { return list<decltype(head::increment()),tail...>(); }
it indeed working :
auto l0 = incrfront<counter<0>>(); // ok, decltype(l0) == list<counter<1>> l0 = list<counter<1>>(); //ok, right type auto l1 = incrfront<counter<0>,counter<1>>(); // ok, decltype(l1) == list<counter<1>,counter<1>> l1 = list<counter<1>,counter<1>>();
now, increment of list, so
template <typename... head, typename tail> auto incrback() -> decltype(list<decltype(head...,tail::increment())>()) { return list<decltype(head...,tail::increment()>(); }
but got error 'incrback' not declared in scope
i tried add method before one:
template <typename... head> auto incrback() -> decltype(list<head...>()) { std::cout << "should not here\n"; return list<head...>(); }
hoping method never called when resolving overloading, method indeed called.
any clue ? want example working :
auto l2 = incrback<counter<1>,counter<1>>(); // want decltype(l2) == list<counter<1>,counter<2>> l2 = incrfront<counter<0>,counter<2>>(); //should possible
first, write code operate on list<>
instead of naked variardic type lists, easier.
second, instead of working template functions, work template classes.
template<typename t> struct inc { typedef decltype(t::increment()) type; }; template<typename t> using inc = typename inc<t>::type;
now can talk inc<head>
instead of decltype( head::increment() )
, should make code far more readable.
write following template
classes:
template<typename list, typename t> struct append; template<typename list, typename t> using append = typename append<list,t>::type; template<template<typename...>class typelist, typename... ts, typename t> struct append<typelist<ts...>, t> { typedef typelist<ts..., t> type; }; template<typename list> struct reverse; template<typename list> using reverse = typename reverse<list>::type; template<template<typename...>class typelist> struct reverse<typelist<>> { typedef typelist<> type; }; template<template<typename...>class typelist, typename t0, typename... ts> struct reverse<typelist<t0, ts...>> { typedef append< reverse<typelist<ts...>>, t0 > type; };
and similar ones. note operate on types, , specialize on types produced generic variardic pack of types passed template
-- means i'm not tied working 1 way pack variardic args single type.
i write template
aliases reduce typename
spam.
next, apply functor:
template<template<typename>class func, typename list> struct apply_to_first; template<template<typename>class func, typename list> using applytofirst = typename apply_to_first<func, list>::type; template<template<typename>class func, template<typename...>class typelist, typename t0, typename... ts> struct apply_to_first<func, typelist<t0, ts...>> { typedef typelist< typename func<t0>::type, ts... > type; };
and incfirst
:
template<typename list> using incfirst = applytofirst< inc, list >;
which pretty short.
as inclast
, marginally harder:
template<typename list> using inclast = reverse< incfirst < reverse<list> > >;
but still fits on 1 line. still, i'd prefer more verbose version:
template<template<typename>class func, typename list> using applytolast = reverse< applytofirst< func, reverse<list> > >; template<typename list> using inclast = applytolast< inc, list >;
now, did not directly answer question, in never wrote incrfront
(nor did compile above, full of syntax errors).
so here incrfirst
, incrlast
after have moved heavy lifting above mini metaprogramming library:
template<typename... ts> incfirst<list<ts...>> incrfirst() { return incfirst<list<ts...>>(); } template<typename... ts> inclast<list<ts...>> incrlast() { return inclast<list<ts...>>(); }
Comments
Post a Comment