显式指定模板参数为函数类型时,为何参数类型与模板参数不同?
模板参数T与函数参数cmp的类型差异原因
你的代码里出现的类型差异,核心是C++中函数类型和函数指针类型的区别,以及函数参数类型的自动调整规则:
模板参数T的类型来源
你显式指定test的模板参数为decltype(cmp1),而cmp1是一个普通函数,decltype(cmp1)直接获取的是该函数的原始函数类型:bool(int&, int&)——这是一种抽象的函数类型,不是指针。函数参数cmp的类型被自动调整
C++不允许函数参数的类型直接是函数类型,当你把T(函数类型)作为函数参数的类型时,编译器会自动将其调整为对应的函数指针类型。也就是说,void test(T cmp)里的cmp,实际类型是bool (*)(int&, int&)(指向该函数的指针类型),而非原本的函数类型。
这时候用decltype(cmp)获取的就是这个被调整后的函数指针类型,自然和模板参数T的函数类型不一致。
验证示例
可以用static_assert直观验证两者的类型差异:
#include <type_traits> bool cmp1(int &a, int &b) { return a < b; } template<typename T> struct S; template<typename T> void test(T cmp) { // 验证T是函数类型 static_assert(std::is_same_v<T, bool(int&, int&)>); // 验证cmp的类型是函数指针类型 static_assert(std::is_same_v<decltype(cmp), bool(*)(int&, int&)>); } void foo() { test<decltype(cmp1)>(cmp1); }
这段代码可以正常编译,直接证明了两者的类型区别。
关键规则回顾
- 函数名本身的类型是函数类型,但当它作为函数参数传递时,会自动发生函数到指针的隐式转换(除非用
decltype取类型、或用&显式取地址的场景)。 - 若函数参数被声明为函数类型,编译器会自动将其调整为对应的函数指针类型,这是C++的默认行为。
内容的提问来源于stack exchange,提问作者XuanInsr
相关产品推荐
相关产品推荐

