2015-10-12 38 views
9

我的問題是關於靜態成員初始值設定項的lambda範圍。考慮下面的測試:靜態成員初始值設定項的lambda範圍

#include <functional> 
#include <iostream> 

struct S { 
    static const std::function<void(void)> s_func; 
}; 

const std::function<void(void)> S::s_func = []() { 
    std::cout << "Hello from " << __PRETTY_FUNCTION__ << std::endl; 
}; 

int main(void) { 
    S::s_func(); 
    return 0; 
} 

GCC從4.8開始定義S的範圍拉姆達,所以程序輸出這樣的事情:

Hello from S::<lambda()> 

(GCC-4.8.2具有不同的定義爲__FUNCTION__ &鈷宏,但儘管如此拉姆達仍然內S定義)

同時GCC-4.7定義在全球範圍內拉姆達,所以程序輸出

Hello from <lambda()> 

可能更新的gcc更符合標準。不過,我想問一下標準是否確實指定了這個方面,或者它可以取決於實現。

更新:爲@ user5434961建議所有__FUNCTION__ -alike宏爲實現相關的,所以最好避免他們在一個符合標準的測試。因此,這裏是可以的,如果編譯器S範圍內定義了這樣的lambda表達式否則打破了彙編編譯的例子:

#include <functional> 
#include <iostream> 

struct S { 
    static const std::function<void(void)> s_func; 
private: 
    static const int s_field; 
}; 

const std::function<void(void)> S::s_func = []() { 
    std::cout << "Hello from S::s_func. S::s_field = " << S::s_field << std::endl; 
}; 

const int S::s_field = 1; 

int main(void) { 
    S::s_func(); 
    return 0; 
} 
+0

我想你應該在更新的例子中將'S :: s_field'更改爲's_field'?否則,我認爲它總是編譯任何範圍。 – Lingxi

+0

那麼,因爲'S :: s_field'是私有的,所以它不能從全局範圍訪問,所以代碼確實會破壞GCC-4.7上的編譯的確如此 – user3159253

+0

是的,是的。我忽視了私人事物。 – Lingxi

回答

7

之前,但我無法找到相關的bug報告這個問題已經被提出。下面是一個broken link,這是一個據稱已提交的MSVC錯誤報告(它在2015年仍未修復:您可以在rise4fun進行測試)。但是GCC的固定值在4.7到4.8之間。用於支持這一行動作爲一個錯誤的相關standardese是:

[C++ 11,9.4.2/2]在一個 static數據成員的德音響nition的初始化表達是同類的範圍。

[C++ 11,5.1.2/2] lambda表達式的評估導致臨時值(12.2)。這個臨時對象稱爲閉包對象。 lambda表達式不應出現在未評估的操作數中(第5章)。 lambda表達式的類型(也是閉包對象的 類型)是一個唯一的,未命名的不聯合類類型 - 稱爲閉包類型 - 其屬性如下所述。這個 類的類型不是聚合(8.5.1)。封閉類型在 包含相應的lambda表達式的最小塊範圍,類範圍或名稱空間範圍內聲明爲 。

以前

Why lambda in static initializer can't access private members of class in VC++2013?

C++11 lambdas can access my private members. Why?

Why is it not possible to use private method in a lambda?

4

我想這應該是在類範圍。從cppreference引述(重點煤礦):

拉姆達表達構建一個無名prvalue臨時對象唯一無名不癒合非聚合類型,被稱爲閉合類型的 , 被聲明(對於ADL的目的)在包含lambda 表達式的最小塊 作用域,類作用域或命名空間範圍內。

S::s_func的亂線定義,你進入的S遇到時間S::範圍。所以,lambda表達式包含在S的類範圍中。由於較近類型是S的成員,因此可以訪問私人成員S

+0

感謝你和@ user5434961同樣有幫助的答案。因爲它比你早一點,所以我把他的回答標記爲接受。 – user3159253

+0

@ user3159253不客氣:)用戶5434961的回答比我的引用標準文檔要好。 – Lingxi