c++templatestemplate-argument-deduction

Avoid to specity template argument when using a function


I want to write a template function that take a std::function as argument, something like:

 template<typename T>
 void registerDelegate(std::function<void(const T&)> d) {
   d(T{});
 }

When I want to use it, I need to write in an explicit way the T template argument:

 auto d = [](const std::string& message) { int i = 0; };
 registerDelegate<std::string>(d);

that's annoying since I've already defined it in the lambda. Is there a way to avoid it and simply write:

registerDelegate(d);

When I want to use the function, while always knowing what T is?


Solution

  • You could forward whatever functor that is supplied to registerDelegate to a lambda (or function template𝅘𝅥𝅮 ) taking a std::function<void(const T&> to deduce T.

    template <class F>
    void registerDelegate(F&& d) {
        []<class T>(std::function<void(const T&)> del) {
            del(T{});
        }(std::function(std::forward<F>(d))); // use std::function's deduction guides
    }
    

    𝅘𝅥𝅮 Instead of changing your current function template which already matches on std::function<void(const T&)>, you could add a function template for functors/functions not already wrapped up in a std::function:

    template<class F>
    decltype(auto) registerDelegate(F&& func) {
        // call your already existing function:
        return registerDelegate(std::function(std::forward<F>(func)));
        //                           ^ use std::function's deduction guides
    }