1

What we usually do is like this:

template<class Callback>  
void some_func(Callback const& callback){
   ....
}

What I want is like:

template<class void Callback(int)>  //<---
void some_func(Callback const& callback){// not valid
   ....
}

We can specify the type if we pass by std::function but it disable inlining.

somebody4
  • 505
  • 4
  • 14
  • 1
    [function_view](https://vittorioromeo.info/index/blog/passing_functions_to_functions.html) might interest you. – Jarod42 May 21 '20 at 13:39

2 Answers2

3

If you have C++20 that's is exactly what the concepts are for

#include <concepts>

template<typename T>
concept Callback = requires(T a) {
    { a(int()) }  -> std::same_as<void>; 
};

template<Callback T> 
void some_func(T const& callback){
  //  ....
}

int a(int) {
    return 0;
}

void b(int) {}

int main() {
    // below does not compile
   // some_func(a);
    some_func(b);
}
bartop
  • 9,971
  • 1
  • 23
  • 54
2

You can use std::enable_if with std::is_invocable (requires C++17 but can be implemented in C++ 14):

#include <type_traits>
#include <iostream>
#include <string>

template <typename F,
          typename = std::enable_if_t<std::is_invocable_v<F, int>>>
void foo(F&& f)
{
    f(1);
}

int main()
{
    // OK
    foo([](int x) { std::cout << x << std::endl; });

    // Still compiles since int is convertible to double
    foo([](double x) { std::cout << x << std::endl; });

    // Compilation error
    // in gcc:
    // error: no matching function for call to 'foo(main()::<lambda(std::string)>)'
    foo([](std::string x) { std::cout << x << std::endl; });
}
dewaffled
  • 2,850
  • 2
  • 17
  • 30