我尝试了下面的代码(https://godbolt.org/z/rcfPK451M)
bool cmp1(int &a, int &b) { return a < b; }
template<typename T> struct S;
template<typename T> void test(T cmp) {
S<T> t;
S<decltype(cmp)> s;
}
void foo() {
test<decltype(cmp1)>(cmp1);
}并得到以下编译错误:
<source>:5:10: error: 'S<bool(int&, int&)> t' has incomplete type
5 | S<T> t;
| ^
<source>:6:22: error: 'S<bool (*)(int&, int&)> s' has incomplete type
6 | S<decltype(cmp)> s;
| ^这表明T是bool(int&, int&)类型,cmp是bool (*)(int&, int&)类型。
我搞不懂他们为什么有不同的类型。
发布于 2022-10-15 18:49:32
您正在使用该函数类型(参数cmp)声明一个变量,因此该类型退化为函数指针类型。您不能拥有具有函数类型的变量,而只能具有指向函数的指针。
标准说tem.扣减/3:
在执行此替换后,8.3.5中描述的函数参数类型调整是按格式进行的.[示例:“void ()(const,int5)”参数类型变为“void()( int,int)”。-最终例子]
简而言之,这种衰减是因为变量是函数模板的参数,并且在类型推断之后发生。如果您尝试decltype(cmp1) a = cmp1;,则不会发生这种情况,因为decltype(cmp1) a实际上声明了一个函数,因此不需要发生衰变(然后您就不能将其分配给一个函数)。
在test中,T仍然是函数类型,因为您使用decltype(cmp1)显式地指定了它。删除它,让模板参数的演绎发生,你可以看到它被推导成腐朽的类型(因为这是参数cmp的实际类型)。
这与使用std::decay (对于函数类型等效于std::add_pointer )是一样的:
S<std::decay_t<T>> t;https://stackoverflow.com/questions/74082118
复制相似问题