Is it possible to call a member function for every type in a tuple?
Asked Answered
D

1

0
namespace details {
template <std::size_t I = 0, typename Tuple, typename Function, typename... Args>
typename std::enable_if<I == std::tuple_size<Tuple>::value, void>::type ForEach(Tuple &t, Function f, Args &... args) {}

template <std::size_t I = 0, typename Tuple, typename Function, typename... Args>
typename std::enable_if<(I < std::tuple_size<Tuple>::value), void>::type ForEach(Tuple &t, Function f, Args &... args) {
    f(std::get<I>(t), args...);
    ForEach<I + 1>(t, f, args...);
}
}

An implementation for ForEach functionality for all types of a tuple is above. It calls f(tuple_type, args...)

However I want something like tuple_type.f(args...) where f and args are template arguments.

f would be a member function of all the types in the tuple, taking args... as arguments.

template <typename... Types>
class TupleManager {
    std::tuple<Types...> t;
    template <typename Function, typename... Args>
    void ForEach(Function f, Args& ... args) {
         details::ForEach<>(t, f, args...);
    }
}

Clarification: f needs to be a member function, i.e a function that takes the same name for all types in the tuple.

Eg:

struct A {
    void foo() {
        std::cout << "A's foo\n";
    }
};
struct B : A {
    void foo() {
        std::cout << "B's foo\n";
    }
};

struct C : A {
    void foo() {
        std::cout << "C's foo\n";
    }
};

But now I can't pass foo. Passing &A::foo print's A's foo. The requirement is to print A'foo for object of A in the tuple, B's foo for object of B in the tuple, and C's foo for object of C in the tuple.

Demo

Dashed answered 6/4, 2017 at 15:41 Comment(4)
I don't know what you are asking. "Something like" with no description of what features of what you typed you actually want is not very clear. What "like" that do you want, what do you need, etc? You want f to be between tuple_type and args...? You want to use exactly that syntax, where f happens to be the name of a common member function? You want exactly that punctuation?Widdershins
Think about how to call your function... ForEach(myTuple, &C::foo)...Toxoid
Change f(std::get<I>(t), args...); to std::get<I>(t).f(args...) and see Jarod's comment.Howze
Have provided a Wandbox link. PAssing &C::foo isn't viable. What is C? C is a type of the tuple. It's not known while calling ForEach. Only's foo is known, or rather that the name foo.Dashed
W
0

The beauty of std::for_each is in its disassociation of function application (on the elements of the range) from iteration (of the range). As such, one doesn't pass the arguments of the call to std::for_each (except for the callee itself that is already passed via the range). Having that in mind, you might want to consider using a different version of for_each that is closer to the std one. Check this one for example: iterate over tuple.

If you're up to a generalisation, you may want to use Jonathan Müller's tuple_iterator. That enables application std algorithms on std::tuples just as if std::tuple were a std container. In particular, you can use std::for_each for your desirable iteration.

Wordless answered 23/7, 2018 at 15:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.