Home:ALL Converter>Infer template argument for pointer to function

Infer template argument for pointer to function

Ask Time:2020-12-07T22:51:26         Author:Tom de Geus

Json Formatter

For the following code:

#include <iostream>
#include <vector>

template <class T>
inline auto foo(const T* A)
{
    return A[0];
}

template <class T>
struct impl
{
    template <typename F>
    static auto bar(const T& A, F func)
    {
        return func(&A[0]);
    }
};

int main()
{
    std::vector<size_t> A = {2, 3, 4};
    std::cout << impl<decltype(A)>::bar(A, &foo) << std::endl;
    return 0;
}

I get (with C++14 using clang on macOS) that

main.cpp:23:18: error: no matching function for call to 'bar'
    std::cout << impl<decltype(A)>::bar(A, &foo) << std::endl;
                 ^~~~~~~~~~~~~~~~~~~~~~
main.cpp:14:17: note: candidate template ignored: couldn't infer template argument 'F'
    static auto bar(const T& A, F func)
                ^
1 error generated.

My question is: Why? How can I fix it?

Author:Tom de Geus,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/65183976/infer-template-argument-for-pointer-to-function
NathanOliver :

foo is the name of a template, not the name of a function. bar requires a type, not a template. Fortunately lambda expressions are a fast easy way to wrap generic function into an object type that can be known and do the dispatch for you. That would give you\nstd::cout << impl<decltype(A)>::bar(A, [](const auto& var){ return foo(var); }) \n << std::endl;\n",
2020-12-07T14:56:35
463035818_is_not_a_number :

The issue is actually from foo not from impl. foo is a template and you will an error also for:\nauto x = &foo;\n\nsource>:23:15: error: unable to deduce 'auto' from '& foo'\n 23 | auto x = &foo;\n | ^~~\n<source>:23:15: note: couldn't deduce template parameter 'auto'\n\nI am not suggesting this a the "right" solution, it is just to show how in principle you can get a pointer to the right instantiation of foo:\nint main()\n{\n std::vector<size_t> A = {2, 3, 4};\n std::cout << impl<decltype(A)>::bar(A,\n static_cast<size_t(*)(const decltype(A)::value_type*)>(&foo)) << std::endl;\n return 0;\n}\n\nOr the more readable (thanks to @StoryTeller):\nint main()\n{\n\n std::vector<size_t> A = {2, 3, 4};\n //auto x = &foo<decltype(A)::value_type>;\n std::cout << impl<decltype(A)>::bar(A,&foo<decltype(A)::value_type>) << std::endl;\n return 0;\n}\n\nNote that gcc does emit the same error as for the original. This appears to be a bug in gcc. Removing the // from the line above magically makes it compile also with gcc even though x is not used. The bug seems to be fixed in gcc-trunk: https://godbolt.org/z/noqGEP (see also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54111).",
2020-12-07T14:58:54
yy