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

Popular posts from this blog

blackberry 10 - how to add multiple markers on the google map just by url? -

php - guestbook returning database data to flash -

delphi - Dynamic file type icon -