2016-12-13 109 views
17

考慮下面的代碼片段:void({})中的{}是什麼?

auto f() { return void({}); } 
int main() { f(); } 

什麼也正是在void({}){}
它是如何解釋的?

只是出於好奇,當然。無論如何,我們再走一點。

請注意,GCC 6.1和鏗鏘3.8編譯沒有錯誤(-std=c++14 -pedantic)。
後者不抱怨,前者顯示了一個警告:

警告:列表初始化非類類型不得括號

使用-pedantic-errors相反,GCC以錯誤結束而鏗鏘編譯它。

這種差異是兩個編譯器之一的錯誤嗎?
我的意思是,它應該被接受與否的有效代碼?

+1

在某些語言中,它表示一個空表或列表。但是,在基於類型的語言中,它應該有一個類型說明符。它與作爲初始化程序沒有任何關係,因此imo,它似乎是某種空白塊範圍。 – Chemistpp

+0

聽起來像一個鏗鏘蟲。這轉到[\ [expr.type.conv \]/2](https://timsong-cpp.github.io/cppwp/expr.type.conv#2)'「否則,表達式是指定類型的結果對象是直接初始化([dcl.init])的初始化方法「,這對」void「沒有意義。 –

+0

它看起來是lambda表達式:[link](http://en.cppreference.com/w/cpp/language/lambda) – Raindrop7

回答

15

從一開始就已經在C++語言中存在對void類型的轉換以及返回void值的可能性。提出問題的唯一部分是{}在這方面的作用。

快速實驗鐺

int a({}); 

生成一個錯誤消息說

error: cannot initialize a variable of type 'int' with an rvalue of type 'void' 

這表明鐺解釋{}作爲void值。這似乎是一種非標準行爲。我在語言規範中沒有看到任何地方可以說{}應該在此上下文中生成void值。

但是,由於叮噹時恰好是這種情況,所以在叮噹中編譯void({})並沒有什麼異常。 C++中的任何值都可以轉換爲void類型,這意味着只要編譯器在此上下文中接受{},其餘部分就會自然遵循。

在GCC它實際上是在-pedantic-errors模式的誤差

error: list-initializer for non-class type must not be parenthesized 

所以正式這是一個「錯誤」,而不是在GCC一個「警告」。


什麼是真正發生在這裏的是,開({和關閉})的結合,使這些編譯器把它解釋爲GNU C語言擴展稱爲Statement Expression(這是偶然的鐺,以及支持)。這是,例如,讓下面的代碼編譯

int a = ({ 3; }); 

在該擴展中,表達({})被視爲void類型的語句表達。但是,這與C++中統一的初始化語法衝突。

+1

Clang主幹現在會爲這種情況生成類似GCC的錯誤消息(自[今年11月](https://reviews.llvm.org/D25816))。 –

+0

... [它也高興地診斷OP的代碼](http://melpon.org/wandbox/permlink/fyypiO2iebe2xE2B)。 –

+1

@ T.C。當然,這是我的錯,不要試圖對付後備箱。謝謝。 – skypjack

相關問題