6

Given the following variadic template:

template<typename... Params>
void fun(void(*f)(Params...), Params... params) {
  f(params...);
}

int main() {
  fun(+[](int a, int b) {}, 2, 3);
}

For now when invoking fun with a lambda I need to specify types of all lambda arguments explicitly. It seems redundant since the int, int could be deduced from 2, 3. Is there a way to make it more concise and automatic?

I would like the following to work, but it doesn't:

template<typename... Params>
void fun(void(*f)(Params...), Params... params) {
  f(params...);
}

int main() {
  fun(+[](auto a, auto b) {}, 2, 3);
}

I am compiling with g++ 5.4.0 and -std=c++14.

max66
  • 65,235
  • 10
  • 71
  • 111
Marcin Król
  • 1,555
  • 2
  • 16
  • 31

1 Answers1

4

Take the function by T instead of by pointer:

template<typename T, typename... Params>
void fun(T f, Params... params) {
  f(params...);
}

int main() {
  fun([](auto a, auto b) {}, 2, 3);
}

That way, the compiler can choose which overload is the right to call at the call site instead if inside the + operator. Just as said in the comment, there is no + operator defined for generic lambdas anyway.


Alternatively, you can disable the compiler from trying to deduce Params from the function pointer by using an identity alias, but I really don't recommend it. Anyway, here you go:

template<typename T>
struct identity { using type = T; };

template<typename T>
using identity_t = typename identity<T>::type;

template<typename... Params>
void fun(void(*f)(identity_t<Params>...), Params... params) {
  f(params...);
}

int main() {
  //  v----- no unary +. That operator is not defined for generic lambdas.
  fun([](auto a, auto b) {}, 2, 3);
}
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • Note that there is no `+` operator for non-generic lambdas either. The built-in `+` operator is used, but the lambda is thereby coerced to a pointer using its conversion operator to function pointer. – Brian Bi Feb 13 '17 at 03:08