与decltype一起使用时的函数类型



我研究了decltypestd::is_same_v,并在函数上试用了它们。

template<typename T>
void func(T t){}
template<typename T>
using f = decltype(func<T>);
template<typename T>
using ff = decltype((func<T>));
template<typename T>
using fff = void(*)(T);

template<typename T, typename U, typename Z>
void test(T t, U u, Z z){
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << std::boolalpha
<< std::is_same_v<T, U> << " "
<< std::is_same_v<U, Z> << " "
<< std::is_same_v<Z, T>;
}
int main()
{
f<int> f1; // 1
ff<int> ff1 = func<int>; // 2
fff<int> fff1 = func<int>;
test(f1, ff1, fff1);
return 0;
}

演示的链接

输出:

void test(T, U, Z) [with T = void (*)(int); U = void (*)(int); Z = void (*)(int)]
true true true

在编辑时,我错误地删除了参数并运行了代码。演示的链接

template<typename T, typename U, typename Z>
void test(T t, U u) // Z z is missing
{ // nothing changed in the body }
no matching function for call to 'test(void (&)(int), void (&)(int), void (*&)(int))'
36 |     test(f1, ff1, fff1);
|                       ^

看起来Z是不同的类型,但std::is_same_v<U, Z>给出了true。我认为fff将是不同的类型,就像引用中的decltype一样

请注意,如果对象的名称用括号括起来,它将被视为普通的左值表达式,因此decltype(x(和decltype((x((通常是不同的类型。


  1. 当我尝试初始化f f1 = func<int>;时,我收到警告和错误
warning: declaration of 'void f1(int)' has 'extern' and is initialized
32 |     f<int> f1 =func<int>;
|            ^~
<source>:32:16: error: function 'void f1(int)' is initialized like a variable
32 |     f<int> f1 =func<int>;
|                ^~~~~~~~~
  1. 当我没有初始化ff ff1;时,我会收到一个错误,说
error: 'ff1' declared as reference but not initialized
33 |     ff<int> ff1 ;
|             ^~~

据我所知,由于decltype((func<T>)),我得到了引用类型,但std::is_same_vtest中给出了true

Apparenty,std::is_same_v告诉这三个都是一样的,但它们是不同的。我是一个c++初学者,我无法理解正在发生的事情。

您的代码类似于:

f<int> f1;                 // `void f1(int);`, function declaration
ff<int> ff1 = func<int>;   // `void (&ff1)(int) = func<int>;`, reference to function
fff<int> fff1 = func<int>; // `void (*fff1)(int) = &func<int>;` pointer to function,
// decay of `func<int>` to pointer

作为C数组,不能按值传递函数;它们衰减为指针。

所以

test(f1, ff1, fff1); // test(&f1, &ff1, fff1);

在测试中,所有参数均为void (*)(int)型。

最新更新