Reputation: 9442
Why can the compiler not match the template parameter F
in the invoke()
Function.
Is there anywhere a non-deduced context I am not aware of??
And how can it be fixed?
// Invoke Function with all tuple arguments.
template<typename F, size_t... Is, typename Tuple>
auto invoke(F&& f, std::index_sequence<Is...>, Tuple&& t)
{
return f(std::get<Is>(t)...);
}
template<typename F, typename Tuple>
auto invoke(F&& f, Tuple&& t)
{
constexpr std::size_t uiLength = std::tuple_size_v<std::remove_reference_t<Tuple>>;
return invoke(std::forward<F>(f),
std::make_index_sequence<uiLength>{},
std::forward<Tuple>(t));
}
template<typename T>
struct A{
using D = int;
};
template<typename... T>
auto make(T&...){
return std::make_tuple(A<T>{}...);
}
int main()
{
invoke([](auto&, auto&){}, std::make_tuple(A<int>{}, A<double>{})); // works
//auto a = invoke(make, std::make_tuple(A<int>{}, A<double>{})); // does not compile, but why??
}
Upvotes: 1
Views: 33
Reputation: 9442
Another solution would be to define the function as a static lambda:
static const auto makeDataHandles = [](auto&... t) {
return std::make_tuple(A<std::remove_reference_t<decltype(t)>>{}...);
}
Upvotes: 0
Reputation: 66230
Is there anywhere a non-deduced context I am not aware of?? And how can it be fixed?
The problem is that you can't pass the name of a template function as argument of a function
template<typename... T>
auto make(T&...){
return std::make_tuple(A<T>{}...);
}
// ...
auto a = invoke(make, std::make_tuple(A<int>{}, A<double>{}));
Try rewriting make()
as a generic (and variadic) lambda (that is an object so you can pass it as argument to a function)
auto a = invoke([](auto & ... rData){ return std::make_tuple(A<decltype(rData)>{}...);},
std::make_tuple(A<int>{}, A<double>{}));
Off Topic suggestion: rename invoke()
with a different name (myInvoke()
, by example) to reduce the risk of a name collision with std::invoke()
.
Upvotes: 2