I am trying to recursively run through a typelist so I can do some run-time code based on each type in the list. I would like to be able to recursively run through all the types in a tuple in a function in a struct (not in a function in the struct) without using "if constexpr" to terminate the recursion.
I have a snippet of code the shows the recursion working with constexpr.
#include <iostream>
#include <string>
#include <tuple>
template <typename ...Ts>
struct temp{
    using TypeList = std::tuple<Ts...>;
    constexpr static std::size_t _N = std::tuple_size<TypeList>::value;
    void print_this()
    { 
        _inner_print<_N,_N>();
    }
    template <std::size_t N, std::size_t MAX>
    void _inner_print()
    {
        if constexpr ( N != 0 )
        {
            std::cout << "Call #"<<MAX-N<<std::endl;
            ////////////////////////
            /* other dynamic code */
            ////////////////////////
            _inner_print<N-1, MAX>();
        }
    }
    TypeList _mem;
};
int main()
{
    std::string name;
    temp<int, int, int> t1;
    t1.print_this();
}
I would like to be able to do the same recursion with C++14, instead of C++17 w/ "if constexpr".
Thank you!
The trick is to use index_sequence. 
Here is a C++14 working solution, improved using @MartinMorterol suggestion.
// -*- compile-command: "g++ -Wall -std=c++14 poub.cpp; ./a.out"; -*-
#include <iostream>
#include <string>
#include <tuple>
#include <type_traits>
template <typename... Ts>
struct temp
{
  using TypeList = std::tuple<Ts...>;
  constexpr static std::size_t _N = std::tuple_size<TypeList>::value;
  void print_this() { _inner_print(std::make_index_sequence<_N>()); }
  template <std::size_t... IDX>
  void _inner_print(std::index_sequence<IDX...>)
  {
    auto dummy = {0, (_inner_print<IDX>(),0)...};
    (void)dummy;
  }
  template <std::size_t IDX>
  void _inner_print()
  {
    std::cout << "\nCall #" << IDX 
              << " sizeof " << sizeof(std::get<IDX>(_mem));
  }
  TypeList _mem;
};
int main()
{
  std::string name;
  temp<int, double, char> t1;
  t1.print_this();
}
which prints:
g++ -Wall -std=c++14 poub.cpp; ./a.out
Call #0 sizeof 4
Call #1 sizeof 8
Call #2 sizeof 1
My initial answer (using recursion)
// -*- compile-command: "g++ -std=c++14 poub.cpp; ./a.out"; -*-
#include <iostream>
#include <string>
#include <tuple>
#include <type_traits>
template <typename... Ts>
struct temp
{
  using TypeList = std::tuple<Ts...>;
  constexpr static std::size_t _N = std::tuple_size<TypeList>::value;
  void print_this() { _inner_print(std::make_index_sequence<_N>()); }
  template <std::size_t... IDX>
  void _inner_print(std::index_sequence<IDX...>)
  {
    _inner_print(std::integral_constant<std::size_t, IDX>()...);
  }
  template <std::size_t HEAD_IDX, typename... TAIL>
  void _inner_print(std::integral_constant<std::size_t, HEAD_IDX>, TAIL... tail)
  {
    std::cout << "\nCall #" << HEAD_IDX 
              << " sizeof " << sizeof(std::get<HEAD_IDX>(_mem));
    // whatever you want HERE ...
    _inner_print(tail...);
  }
  void _inner_print(){};
  TypeList _mem;
};
int main()
{
  std::string name;
  temp<int, double, char> t1;
  t1.print_this();
}
                        If you can change your _inner_print function to a class, you can make use of a partial specialization to end the recursion:
template <std::size_t N, std::size_t MAX>
struct _inner_print
{
    _inner_print()
    {
        std::cout << "Call #"<<MAX-N<<std::endl;
        ////////////////////////
        /* other dynamic code */
        ////////////////////////
        _inner_print<N-1, MAX>();
    }
};
template <std::size_t MAX> struct _inner_print<0, MAX> { };
Rather than calling _inner_print() as a function, it becomes a declaration for an unnamed temporary, invoking the constructor that performs your output.
You should use partial specialization. But you can't do this with a function.
You should use a struct to do the trick.
#include <iostream>
#include <string>
#include <tuple>
template <std::size_t N, std::size_t MAX, class T>
struct inner_print_impl{
        static void run(const T&  caller)
        {
            std::cout << "Call #"<<MAX-N<<  " " << caller.a << std::endl;
            ////////////////////////
            /* other dynamic code */
            ////////////////////////
            inner_print_impl<N-1, MAX , T>::run(caller);
        }
 };
template < std::size_t MAX, class T>
struct inner_print_impl<0, MAX ,  T>{
        static void run(const T&  caller)
        {
            std::cout << "Call #"<<MAX<<  " " << caller.a << std::endl;
            ////////////////////////
            /* other dynamic code */
            ////////////////////////
            // no recursion
        }
 };
template <typename ...Ts>
struct temp{
    using TypeList = std::tuple<Ts...>;
    constexpr static std::size_t N_ = std::tuple_size<TypeList>::value;
    template <std::size_t N, std::size_t MAX, class T>
    friend struct inner_print_impl;
    void print_this()
    { 
        inner_print_impl<N_,N_, temp<Ts...> >::run(*this);
    }
    TypeList _mem;
    private : 
        int a ; // test acces
};
int main()
{
    std::string name;
    temp<int, int, int> t1;
    t1.print_this();
}
Note :
*this to the call and add the new struct as friend of your class/* other dynamic code */ part. You may : 
int instead of size_t and stop at -1 rather than 0
PS :
I don't get the part
in a tuple in a function in a struct (not in a function in the struct)
I hope I didn't miss something
Edit :
My code do one more iteration than your, you may just empty this :
template < std::size_t MAX, class T>
struct inner_print_impl<0, MAX ,  T>{
        static void run(const T&  caller)
        {
        }
 };
And you don't display for the 0 case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With