簡體   English   中英

decltype(function_name)的返回類型完全沒用嗎?

[英]the return type of decltype(function_name) is totally useless?

void foo(int a) {
    cout << "Hello" << a << '\n';
}

根據decltype的規則,decltype(foo)的類型應為“ void foo(int)”,但似乎我們無法采取任何措施:

void (& f_ref)(int) = foo;
void (* f_ptr)(int) = foo;


cout<<is_same_v<decltype(foo), decltype(f_ref)><<endl; //return 0
cout<<is_same_v<decltype(foo), decltype(f_ptr)><<endl; //return 0
decltype(foo) df;
df = foo;    //error: assignment of function ‘void df(int)’
df = &foo;   //error: assignment of function ‘void df(int)’

decltype(foo) df{foo}; //error: function ‘void df(int)’ is initialized like a variable
decltype(foo) df{&foo}; //error: function ‘void df(int)’ is initialized like a variable

聲明一個變量:

decltype(foo)* pf = foo;
pf(42);

使用std::function函數包裝器:

std::function<decltype(foo)> f = foo;
f(42);

您的摘要中的兩個is_same_v被評估為0因為類型不同。

dectype(foo)void (int) (不是void foo(int) ,名稱不是該類型的一部分),
這與void (&)(int)f_ref的類型)和void (*)(int)f_ptr的類型)不同。


這行:

decltype(foo) df{foo};

不能僅僅因為語法不允許您在函數聲明中使用初始化程序而進行編譯。

即使沒有decltype它也不起作用:

void df(int) {foo}; // error: expected ';' before '}' token

雖然可以創建指向decltype(foo)的指針:

decltype(foo) *df{foo}; // Becomes `void (*df)(int) {foo};`

這些行:

df = foo;
df = &foo;

不要編譯,因為您不能分配給函數。 即使df void df(int);也行不通void df(int);


如何使用此類型?

有無數用途。 例如,您可以使用它如上所述創建指向此函數的指針,也可以將其用作模板參數(用於std::function或其他東西)。

您可以使用它來聲明具有與函數相同簽名的功能對象:

using ffoo = ::std::function<decltype(foo)>;

decltype(function_name)的返回類型是否完全沒有用?

當然不。 現場例子

void f1();
void f2(int);
void f3();

int main()
{
    std::cout << "f1 - f2 " << std::is_same<decltype(f1),decltype(f2)>::value << std::endl;
    std::cout << "f1 - f3 " << std::is_same<decltype(f1),decltype(f3)>::value << std::endl;
}

例如,可以與std::enable_if一起使用。

在此聲明中

cout<<is_same_v<decltype(foo), decltype(f_ref)><<endl;

左模板參數是函數類型,而右模板參數是引用類型。 要比較類型,您應該刪除引用。

在此聲明中

cout<<is_same_v<decltype(foo), decltype(f_ptr)><<endl;

比較了函數類型和指向函數的指針。

因此,兩個語句都返回0(假)。

這些陳述

df = foo; 
df = &foo;

沒有道理。 您可能無法分配功能。

這些陳述

decltype(foo) df{foo}; 
decltype(foo) df{&foo};

也沒有道理。

您可以在類中聲明例如decltype( foo )類型的函數,然后對其進行定義。

這是一個演示程序。

#include <iostream>
#include <type_traits>

void foo( int a ) 
{
    std::cout << "Hello " << a << '\n';
}

struct A
{
    decltype(foo) df;
};

void A::df( int a )
{
    std::cout << "Bye " << a << '\n';
}

int main() 
{
    foo( 0 );
    A a;

    a.df( 1 );

    void (& f_ref)(int) = foo;
    void (* f_ptr)(int) = foo;

    std::cout << std::is_same<decltype(&foo), decltype( f_ptr )>() << std::endl;
    std::cout << std::is_same<decltype(foo), std::remove_reference_t<decltype( f_ref )>>() << std::endl;

    return 0;
}

它的輸出是

Hello 0
Bye 1
1
1

考慮到此聲明中

void (& f_ref)(int) = foo;

函數指定foo被隱式轉換為指向函數的指針。

這完全是應該的。 如果您寫了void(int) df; ,那顯然是錯誤的。 您正在嘗試使用函數類型聲明變量,但沒有意義。 可能有意義的唯一上下文是聲明一個函數對象: auto bar = std::function<decltype(foo)>; 現在bar是一個對象,該對象引用類型為void(int)的函數(或類似函數的實例,例如lambda void(int)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM