1

Most of the questions I have found revolve around non-member functions where the variadic template parameters are also found in the function's arguments.

In my case, I am in a situation where I would like to filter the types coming into one of the variadic member functions and pass the filtered types to another variadic member function:

#include <tuple>
#include <type_traits>

template<typename...Ts>
using tuple_cat_t = decltype(std::tuple_cat(std::declval<Ts>()...));

// how the filtering of the types happen is not relevant
template<typename T, typename...Ts>
using remove_t = tuple_cat_t<
    typename std::is_empty_v<T>,
        std::tuple<>,
        std::tuple<Ts>
    >::type...
>;

struct Foo
{
    template <typename... T_Tags>
    void Bar(float arg)
    {
        // I would like to call DoBar() with a filtered set of T_Tags
        // where type filtering is done with something similar to what is outlined
        // here: https://stackoverflow.com/a/23863962/368599
        using filtered_args = std::remove_t<T_Tags...>;

        // not sure of the syntax here or if this is even possible
        std::invoke(&Foo::DoBar<???filtered_args???>, std::tuple_cat(std::make_tuple(this), std::make_tuple(arg)));
    }

    template <typename... T_FilteredTags>
    void DoBar(float arg)
    {
        // Do something with T_FilteredTags types
    }
};
Samaursa
  • 16,527
  • 21
  • 89
  • 160
  • @SamVarshavchik I'll edit the question a bit as I would like filtered args to be passed. I am not sure of the syntax of `std::invoke` for variadic member function calls or if that is even possible – Samaursa Jul 21 '22 at 18:28
  • `DoBar` receives a `float`, but you pass in a `tuple`? – 康桓瑋 Jul 21 '22 at 18:29
  • @康桓瑋 because `Foo::DoBar` is a member function, I have to pass in `this` somehow - again, I'm not sure of the syntax to pass `this` as well as the float argument – Samaursa Jul 21 '22 at 18:31
  • Do you mean something like this? https://gcc.godbolt.org/z/h8e3c8oxd – Simon Kraemer Jul 21 '22 at 19:10
  • 1
    @SimonKraemer the answer from 康桓瑋 is what I was looking for although your solution gives me an alternative if there is no C++20 support – Samaursa Jul 25 '22 at 17:35

1 Answers1

1

You can use template lambda to expand the filtered types and specify them to DoBar explicitly

struct Foo
{
    template <typename First_Tag, typename... T_Tags>
    void Bar(float arg)
    {
        using filtered_args = remove_t<First_Tag, T_Tags...>;

        [&]<typename... T_FilteredTags>(std::tuple<T_FilteredTags...>*) { 
          std::invoke(&Foo::DoBar<T_FilteredTags...>, this, arg);
        } (static_cast<filtered_args*>(nullptr));
    }

    template<typename... T_FilteredTags>
    void DoBar(float arg)
    {
      // Do something with T_FilteredTags types
    }
};

Noted that there is no need to use tuple to concatenate this and arg, just pass them to std::invoke directly.

Demo

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • I♥λ. C++ could have been a simpler language if lambdas had been part of it from the beginning. (Maybe it would have been Lisp.) – Solomon Slow Jul 21 '22 at 18:54
  • that worked well, although I had to turn on C++20 support - is there an equivalent way of doing this in C++17? – Samaursa Jul 25 '22 at 17:31