Search code examples
c++boostboost-hana

Create a function signature from a hana tuple without the preprocessor


Is there a way to do this whitout the preprocessor?

#include <boost/hana.hpp>
#include <boost/preprocessor.hpp>

namespace ba = boost::hana;

template <typename Arguments, unsigned ArgCount>
struct FunctionSigCreatorImpl {};

template <typename Arguments>
struct FunctionSigCreator : FunctionSigCreatorImpl<Arguments, decltype(ba::length(Arguments{}))::value>
{
};

#define DEF_ARG(z, n, data) \
    typename decltype(+ba::at(Arguments{}, ba::int_c<n>))::type

#define DEF_FUN_CREATOR(z, argCount, data)                                                  \
    template <typename Arguments>                                                         \
    struct FunctionSigCreatorImpl<Arguments, argCount>                                    \
    {                                                                                       \
        using Type = void(BOOST_PP_ENUM(argCount, DEF_ARG,));      \
    };

BOOST_PP_REPEAT(19, DEF_FUN_CREATOR,)

int main(int argc, char **argv)
{
    using MyTuple = ba::tuple<ba::type<int>, ba::type<long>, ba::type<char>>;
    static_assert(std::is_same<typename FunctionSigCreator<MyTuple>::Type, void(int, long, char)>::value);

    return 0;
}

Solution

  • #include <boost/hana.hpp>
    #include <boost/hana/tuple.hpp>
    
    namespace ba = boost::hana;
    
    template<typename ... Types>
    ba::type<void(typename Types::type...)> FunctionSigCreatorImpl(ba::tuple<Types...>){ return{}; }
    
    template<typename Tuple>
    using FunctionSigCreator = decltype(FunctionSigCreatorImpl(std::declval<Tuple>()));
    
    int main()
    {
        using MyTuple = ba::tuple<ba::type<int>, ba::type<long>, ba::type<char>>;
        //using MyTuple = decltype(ba::tuple_t<int,long,char>);
        static_assert(std::is_same<typename FunctionSigCreator<MyTuple>::type, void(int, long, char)>::value);
    
        return 0;
    }