2392


C++11で静的データメンバ定義(`X::singleton`)のラムダ式中から、該当クラス(`X`)のprivateメソッド(`X::X()`と`X::init()`)にアクセスできるのはどうしてですか？
C++仕様での該当パラグラフを知りたいです。

[code]

    class X {
      X() {}
      void init() {}
    public:
      X(const X&) = default;
      void mf() const {}
      static const X& singleton;
    };
    
    const X& X::singleton = []{
      static X obj;  // X::X()にアクセス可能
      obj.init();    // X::init()にアクセス可能
      return obj;
    }();
    
    int main()
    {
    //  X x;       // X::X()アクセス不可
    //  x.init();  // X::init()アクセス不可
      X::singleton.mf();
    }
    
[/code]

LiveDemo: <http://melpon.org/wandbox/permlink/hqOvjVHyBdfV5HtE>


CC BY-SA 3.0
2014-12-22T15:07:00.473
2389
2015-02-14T01:56:41.487
49
question
c++ c++11
静的データメンバ定義中のラムダ式がクラススコープになる理由


<https://stackoverflow.com/questions/24237729/c11-lambdas-can-access-my-
private-members-why>

こちらに同様の質問があります。101010氏の文を引用させていただきます。

> § 9.4.2/2 Static data members [class.static.data]:
>
> The initializer expression in the deﬁnition of a static data member is in
> the scope of its class.
>
> § 5.1.2/2&3 Lambda expressions [expr.prim.lambda]:
>
> 2 The evaluation of a lambda-expression results in a prvalue temporary
> (12.2). This temporary is called the closure object. A lambda-expression
> shall not appear in an unevaluated operand (Clause 5). [ Note: A closure
> object behaves like a function object (20.9).-end note]
>
> 3 The type of the lambda-expression (which is also the type of the closure
> object) is a unique, unnamed nonunion class type - called the closure type -
> whose properties are described below. This class type is not an aggregate
> (8.5.1). The closure type is declared in the smallest block scope, class
> scope, or namespace scope that contains the corresponding lambda-expression.

補足をしますが、まずstaticデータメンバの初期化式のスコープがクラスのものになるという点ですが、これはC++03から存在する文面です。

デモのコードは、実際には以下の様なコードと同義になります。  
ただし、以下は擬似コードであり、実際に生成されるコードは処理系に依存します。

[code]

    class X {
        X() {}
        void init() {}
    public:
        X(const X&) = default;
        void mf() const {}
        static const X& singleton;
    
    private:
        struct Lambda
        {
            const X& operator()(){
                static X obj;  // X::X()にアクセス可能
                obj.init();    // X::init()にアクセス可能
                return obj;
            }
        };
    };
    
    const X& X::singleton = Lambda{}();
    
    int main()
    {
    //  X x;       // X::X()アクセス不可
    //  x.init();  // X::init()アクセス不可
        X::singleton.mf();
    }
    
[/code]

default指定を使用せず、Lambda{}()をLambda()()に書き換えれば、C++03でも動作します。


CC BY-SA 3.0
2014-12-22T16:06:15.773
2392
2015-02-14T01:56:41.487
2017-05-23T12:38:55.250
-1
5529
2389
answer