std::function vs callable as template parameter

400 views Asked by At

In the example below, why line 20 causes the error described from line 27 to 30?

Calling exec1 in line 33 works fine.

#include <cstdint>
#include <functional>
#include <iostream>
#include <tuple>
#include <type_traits>

template <typename... t_fields>
void exec0(std::function<std::tuple<t_fields...>()> generate,
           std::function<void(t_fields &&...)> handle) {
  std::tuple<t_fields...> _tuple{generate()};
  std::apply(handle, std::move(_tuple));
}

template <typename t_generate, typename t_function>
void exec1(t_generate generate, t_function handle) {
  auto _tuple{generate()};
  std::apply(handle, std::move(_tuple));
}

int main() {
  auto _h = [](uint32_t u) -> void { std::cout << "u = " << u << '\n'; };

  auto _g = []() -> std::tuple<uint32_t> { return std::tuple<uint32_t>{456}; };

  //  exec0<uint32_t>(_g, _h);
  /*
main.cpp:25:3: error: no matching function for call to 'exec0'
main.cpp:8:6: note: candidate template ignored: could not match
'function<tuple<unsigned int, type-parameter-0-0...> ()>' against '(lambda at
/var/tmp/untitled002/main.cpp:23:13)'
  */

  exec1(_g, _h);

  return 0;
}

g++ --version replies:

g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1

There are 1 answers

0
HolyBlackCat On BEST ANSWER

Even though you specified <uint32_t> as a template argument, the compiler seems to try to deduce more elements for the parameter pack, fails to do so (because the type of a lambda is not std::function<...>), and becomes upset.

You need to somehow inhibit template argument deduction.

Either call it as exec0<uint32_t>({_g}, {_h});, or wrap parameter types in std::type_identity_t<...> (or, pre-C++20, std::enable_if_t<true, ...>).

Then the compiler will accept your uint32_t as the only type in the pack, and won't try to add more types.