模板参数推导不适用于函数模板 <unresolved overloaded function type>

Template argument deduction Doesn't Work for Function Template <unresolved overloaded function type>

我想了解模板参数推导在 C++ 中的工作原理。所以写出不同的例子。下面给出了一个这样的例子,它不起作用,我不明白为什么:

#include<iostream>
template<int var, typename T>
void func (T x)
{
    std::cout<<x<<std::endl;
}

template<typename T>
void SomeFunc(T a)
{
    a(6);
}
int main()
{
    
    
    func<5, int>(10);//this work as expected
    func<5>(20);//this works as well using template argument deduction
    
   
    SomeFunc(func<5,int>) ;//this works as well
    
    
    //the next two calls doesn't work
    
    SomeFunc(func<5>);//this doesn't work. Why doesn't template argument deduction works here
    SomeFunc(func<5>(20));//this doesn't work either.
   
    
    return 0;
}

在上面的示例中,语句 SomeFunc(func<5>); 不起作用。我的想法是,当编译器尝试实例化 SomeFunc<> 时,它需要它的模板类型参数。但是我们已经将 func<5> 作为函数调用参数传递,而没有实际调用(将调用参数指定给 func 本身) func 因此无法推导出第二个参数,因此它不起作用。我的第一个问题 是我对为什么这个调用失败的分析正确吗?如果不是那么为什么它不起作用。

接下来在语句 SomeFunc(func<5>(20)); 中,我已将函数调用参数 20 指定为 func,这在之前的调用中未指定。但是这个声明仍然不起作用。 为什么会这样

在阅读有关模板参数推导的内容时,我还遇到了以下语句:

Deduction only works for immediate calls.

但是我不明白上面引用的语句是什么意思。它可能与完整类型或不完整类型用作模板参数这一事实有关,但我不确定。

func<5> 是对 func 的无效调用,因为您必须使用括号来调用函数,即使对于采用 0 个参数的函数也是如此。至于第二个错误,func<5>(20) 是有效的,因为编译器能够从函数的参数类型中推断出 T。但是,您不能有 void 变量。因此,使用 void 值调用 SomeFunc 是无效的,因为 a 不能是 void 参数。

static_assert(std::is_same_v<decltype(func<5>(20)), void>);

SomeFunc(func<5>(20)); // T is deduced as void
  • SomeFunc(func<5,int>);
    

    您将指针传递给函数 func<5,int>,然后 T 变为 void(*)(int),这很好。当您使用函数指针 a 调用它指向的函数时,它也可以在 inside SomeFunc 中工作。

  • SomeFunc(func<5>);
    

    无法扣除。编译器无法期待在 SomeFunc 中看到您将调用 a(6),因此它必须实例化 func<5,int> 并使 a 指向它。

  • SomeFunc(func<5>(20));
    

    此处您实际上调用了 func<5,int>(使用参数 20)并将该调用的 return 值传递给 SomeFuncfunc<5,int> 没有 return 值,因为它是 void 并且 void a; 无效。如果 有效,下一个问题就是您尝试在 SomeFunc 中调用 aSomeFunc 的参数必须是某种可调用的,否则 a(6); 将失败。