可变参数元组调用函数中的模板参数不匹配

时间:2019-05-09 18:08:00

标签: templates c++17 variadic-templates argument-deduction generic-lambda

为什么编译器不能匹配F函数中的模板参数invoke()。 有没有我不知道的非推论上下文? 以及如何解决?

Live

// 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??
}

2 个答案:

答案 0 :(得分:2)

  

哪里有我不知道的非推论上下文?以及如何解决?

问题是您不能将模板函数的名称作为函数的参数传递

template<typename... T>
auto make(T&...){
    return std::make_tuple(A<T>{}...);
}

// ...

auto a = invoke(make, std::make_tuple(A<int>{}, A<double>{}));

尝试将make()重写为通用(和可变参数)lambda(这是一个对象,因此您可以将其作为参数传递给函数)

auto a = invoke([](auto & ... rData){ return std::make_tuple(A<decltype(rData)>{}...);},
                std::make_tuple(A<int>{}, A<double>{}));

非主题建议:将invoke()重命名为另一个名称(例如myInvoke()),以减少与std::invoke()发生名称冲突的风险。

答案 1 :(得分:0)

另一种解决方案是将函数定义为静态lambda:

static const auto makeDataHandles = [](auto&... t) {
    return std::make_tuple(A<std::remove_reference_t<decltype(t)>>{}...);
}