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

function type when used with 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;
}

link to the demo

输出:

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

在编辑时我错误地删除了参数和 运行 代码。 link to the demo

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 in cpprefernce

会是不同的类型

Note that if the name of an object is parenthesized, it is treated as an ordinary lvalue expression, thus decltype(x) and decltype((x)) are often different types.


  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

Apparenlty,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) 类型。