Consider this working code:
#include <iostream>
#include <utility>
#include <array>
template <typename... Args>
void foo (Args&&... args) {
const auto v = {args...};
for (auto x : v) std::cout << x << ' '; std::cout << '\n';
}
template <typename> struct Foo;
template <std::size_t... Is>
struct Foo<std::index_sequence<Is...>> {
template <typename Container>
static void execute (const Container& v) {
foo(v[Is]...);
}
};
template <std::size_t N>
void fooArray (const std::array<int, N>& a) {
Foo<std::make_index_sequence<N>>::execute(a);
}
int main() {
fooArray<6>({0,1,2,3,4,5}); // 0 1 2 3 4 5
}
I want to now generalize the Foo
struct like so:
#include <iostream>
#include <utility>
#include <array>
template <typename... Args>
void foo (Args&&... args) {
const auto v = {args...};
for (auto x : v) std::cout << x << ' '; std::cout << '\n';
}
template <typename> struct Foo;
template <std::size_t... Is>
struct Foo<std::index_sequence<Is...>> {
template <typename Container, typename F> // *** Modified
static void execute (const Container& v, F f) {
f(v[Is]...);
}
};
template <std::size_t N>
void fooArray (const std::array<int, N>& a) {
Foo<std::make_index_sequence<N>>::execute(a, foo);
}
int main() {
fooArray<6>({0,1,2,3,4,5});
}
But I get a compile error (from GCC 4.9.2) that F cannot be deduced. How do I achieve this?
foo
is a family of overloads, and so the foo
is ambiguous.
(even foo<int, int>
is, as it may have additional type too).
You may force expected type function as follow:
template <std::size_t... Is>
struct Foo<std::index_sequence<Is...>> {
template <typename Container>
static void execute (const Container& v, void (*f)(decltype(v[Is])&...)) {
f(v[Is]...);
}
};
An alternative is to wrap function foo
into a class:
class FooCaller
{
public:
template <typename... Args>
void operator () (Args&&... args) const {
const auto v = {args...};
for (auto x : v) std::cout << x << ' '; std::cout << '\n';
}
};
and keep your implementation: