模板参数推导不适用于函数模板 <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 值传递给 SomeFunc
。 func<5,int>
没有 return 值,因为它是 void
并且 void a;
无效。如果 有效,下一个问题就是您尝试在 SomeFunc
中调用 a
。 SomeFunc
的参数必须是某种可调用的,否则 a(6);
将失败。
我想了解模板参数推导在 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
调用它指向的函数时,它也可以在 insideSomeFunc
中工作。 -
SomeFunc(func<5>);
无法扣除。编译器无法期待在
SomeFunc
中看到您将调用a(6)
,因此它必须实例化func<5,int>
并使a
指向它。 -
SomeFunc(func<5>(20));
此处您实际上调用了
func<5,int>
(使用参数20
)并将该调用的 return 值传递给SomeFunc
。func<5,int>
没有 return 值,因为它是void
并且void a;
无效。如果 有效,下一个问题就是您尝试在SomeFunc
中调用a
。SomeFunc
的参数必须是某种可调用的,否则a(6);
将失败。