0
    namespace easy_random {

    template<typename First_T>
    auto make_tuple_of_rands(First_T first) {
        return std::make_tuple(first());
    }

    template<typename First_T, typename... Rest_T>
    auto make_tuple_of_rands(First_T first, Rest_T... rest) {
        return std::tuple_cat(make_tuple_of_rands(first),make_tuple_of_rands(rest...));
    }

    template<typename First_T>
    auto make_tuple_of_n_rands(std::size_t n, First_T first) {
        return std::make_tuple(first(n));
    }

    template<typename First_T, typename... Rest_T>
    auto make_tuple_of_n_rands(std::size_t n, First_T first, Rest_T... rest) {
        return std::tuple_cat(make_tuple_of_n_rands(n, first), make_tuple_of_n_rands(n, rest...));
    }



    template<typename... RandStreamTypes>
    class multi_rand_stream {
        std::tuple<RandStreamTypes...> streams;
    public:
        explicit multi_rand_stream(RandStreamTypes... args);

        explicit multi_rand_stream(std::tuple<RandStreamTypes...> &args);

        auto operator()();

        auto operator()(std::size_t n);
    };

    template<typename... RandStreamTypes>
    multi_rand_stream<RandStreamTypes...>::multi_rand_stream(RandStreamTypes... args) : streams(args...) {}

    template<typename... RandStreamTypes>
    multi_rand_stream<RandStreamTypes...>::multi_rand_stream(std::tuple<RandStreamTypes...> &args) : streams(args) {}

    template<typename... RandStreamTypes>
    auto multi_rand_stream<RandStreamTypes...>::operator()() {
        return std::apply(make_tuple_of_rands, streams);
    }

    template<typename... RandStreamTypes>
    auto multi_rand_stream<RandStreamTypes...>::operator()(std::size_t n) {
        return std::apply(make_tuple_of_n_rands, std::tuple_cat(std::make_tuple(n), streams));
    }
}

I would like to be able to return a tuple composed of the return values from running the members of tup as functors.

I'm currently at a loss as to how to approach doing so. I have tried using apply and recursion with tuple_cat, but it has been having trouble deducing the template typing of the functions.

edit: to include the full class i'm trying to implement, maybe that will expose my error.

KotoroShinoto
  • 720
  • 1
  • 5
  • 9
  • This is not merely a "how do I expand variadics" question. i'm trying to assemble the results into a tuple, and the outputs are of variadic types depending on the functor's result type. the compiler is quite unhappy. Did you actually look at the use case or just see the triple dot and assume I was missing the obvious? – KotoroShinoto Aug 02 '18 at 20:44
  • 2
    How about [this](http://coliru.stacked-crooked.com/a/45b48c695619cf9f)? Classic tag-dispatching with an index sequence to fold over the tuple. – Quentin Aug 02 '18 at 20:48
  • I think that index sequence bit was the missing piece I needed. Let me try to work that into my implementation. – KotoroShinoto Aug 02 '18 at 20:51
  • 2
    Unfortunately, I can't post and answer anymore, but I would simply use `std::apply` to unfold the tuple into a variadic lambda. There you can then receive the tuple elements as a parameter pack, which you can expand into an intializer list that makes a new tuple from calling each element. Example here: https://godbolt.org/g/YF4aKL – Michael Kenzel Aug 02 '18 at 20:51
  • @MichaelKenzel oooh, that's nice. I ditched `std::apply` way too fast indeed! – Quentin Aug 02 '18 at 20:53
  • I was trying to figure out something akin to that @MichaelKenzel, but I was unsuccessful. i'm sure it was due to lack of understanding on my part about some portion of how this system works. – KotoroShinoto Aug 02 '18 at 20:55
  • Frankly, I think my problem was that either I never understood that you could use the triple dots AFTER a function like that, or I forgot about it after reading the docs. Thanks! – KotoroShinoto Aug 02 '18 at 20:56
  • @MichaelKenzel your solution worked with minimal lines of code. You are a gentleman and a scholar :D Shame they marked this a duplicate, I wish I could have granted you a solution credit. – KotoroShinoto Aug 02 '18 at 21:04
  • 1
    :D glad I could help ;) – Michael Kenzel Aug 02 '18 at 21:05
  • @MichaelKenzel question has been reopened, knock youself out :p – Quentin Aug 03 '18 at 14:14
  • @Quentin thanks! =) – Michael Kenzel Aug 03 '18 at 15:11

1 Answers1

2

Answer from comments above: I would simply use std::apply() to unfold the tuple into a variadic lambda. There you can then receive the tuple elements as a parameter pack, which you can expand into an intializer list that makes a new tuple from calling each element:

template<typename... Ts>
class multi_functor
{
    std::tuple<Ts...> tup;

public:
    auto operator()()
    {
        return std::apply([](auto&&... args)
        {
            return std::tuple { args()... };
        }, tup);
    }
};
Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39