c++c++17variadic-templatestemplate-meta-programmingboost-hana

Base case specialization for recursive variadic template


My target is to define a Recursive class, templated on an int N and one or more types T, ...Ts, which should behave like a std::pair with

In trying to write down the class given the above requirements, I've come up with this non-working code (where I've also defined some necessary, as they help a lot, aliases for two instantiations of Recursive), and I don't know if I have mis-designed what I described above (or if it is an ill-formed description!), or if I'm misusing the language syntax.

#include <array>
#include <boost/hana/fwd/optional.hpp>
#include <boost/hana/optional.hpp>
#include <string>
#include <utility>
#include <vector>

template <int N, typename T1, typename T2, typename ...Ts>
struct Recursive
    : std::pair<std::array<T1, N>, 
                boost::hana::optional<std::vector<Recursive<N, T2, Ts...>>>> {};

template <int N, typename T>
struct Recursive<N, T> : std::array<T, N> {};

template<typename ...T>
using Recursive2 = Recursive<2u, T...>;

template<typename ...T>
using Recursive3 = Recursive<3u, T...>;

int main() {
    using boost::hana::nothing;
    Recursive2<int> x(std::make_pair(std::array<int, 2>{0,0}, nothing));
}

I'll add some troubleshooting that I've done so far. In the following the template specilization seems to work just fine.

#include <iostream>

template <int N, typename T, typename ...Ts>
struct Recursive {
    void operator()(){ std::cout << "general\n"; }
};

template <int N, typename T>
struct Recursive<N, T> {
    void operator()(){ std::cout << "specialized\n"; }
};

template<typename ...T>
using Recursive2 = Recursive<2u, T...>;

template<typename ...T>
using Recursive3 = Recursive<3u, T...>;

int main() {
    Recursive2<int>{}();
    Recursive2<int>{}();
    Recursive2<int,int>{}();
}

Solution

  • You have several issues:

    Result is:

    template <int N, typename T1, typename ...Ts>
    struct Recursive;
    
    template <int N, typename T1, typename T2, typename ...Ts>
    struct Recursive<N, T1, T2, Ts...>
        : std::pair<std::array<T1, N>,
                    boost::hana::optional<std::vector<Recursive<N, T2, Ts...>>>
                                >
    {
        using std::pair<
            std::array<T1, N>,
            boost::hana::optional<std::vector<Recursive<N, T2, Ts...>>>>::pair;
    };
    
    template <int N, typename T>
    struct Recursive<N, T>
        : std::pair<std::array<T, N>, decltype(boost::hana::nothing)>
    {
        using std::pair<std::array<T, N>, decltype(boost::hana::nothing)>::pair;
    };
    
    template<typename ...T>
    using Recursive2 = Recursive<2u, T...>;
    
    template<typename ...T>
    using Recursive3 = Recursive<3u, T...>;
    
    int main() {
        using boost::hana::nothing;
        Recursive2<int> x(std::make_pair(std::array<int,2>{0,0}, nothing));
    }
    
    

    Demo