Search code examples
c++templatesfunctor

How to define a template function with two relative parameters


I'm trying to define a function, which allows us to call the standard hash function or some custom-defined function, and return the value of hash.

Here is an example about how to use my function:

auto res = myfunc<std::hash>(2);    //hash the integer 2 with the function std::hash
auto res2 = myfunc<std::hash>("abc");    // hash the string "abc" with the function std::hash
auto res3 = myfunc<customHasher>(2);    // hash the integer 2 with some custom hash function

I've tried to code as below:

template<void (*T)(U)>
size_t myfunc(const U &u)
{
    return T<U>(u);
}

T should be a function pointer, a std::function or a lambda, and U is the type of parameter of T.

But it can't be compiled.

main.cpp:14:23: error: expected ‘>’ before ‘(’ token
     template<void (*T)(U)>
                       ^
main.cpp:15:25: error: ‘U’ does not name a type
     size_t myfunc(const U &u)
                         ^
main.cpp: In function ‘size_t myfunc(const int&)’:
main.cpp:17:18: error: ‘U’ was not declared in this scope
         return T<U>(u);

Well, I know that template<void (*T)(U)> must be wrong because U is not defined. But I don't know how to fix it.


Solution

  • You need to declare both parameters. Moreover, std::hash is a class template, not a function. You can use a template template parameter:

    #include <cstdint>
    #include <functional>
    #include <iostream>
    #include <string>
    
    template<typename T, template<typename> typename H = std::hash>
    std::size_t myfunc(const T &t)
    {
        return H<T>{}(t);
    }
    
    int main() {
        std::cout << myfunc(std::string{"123"});
    }
    

    Though, to use the same with your customHasher it needs to be a class template (with operator()), too.

    Note that you need to explicitly construct a string in main, otherwise T cannot be deduced to be std::string.