2016-06-16 5 views
2

私は回避策があれば疑問は、このような状況です。変数Bは、初期化されていないstd::functionインスタンスを呼び出すことによって初期化されるため、クラッシュします。私の論理では、回避策はまずstd::functionを初期化してから、メンバーBを初期化することです。しかし、その後、このようなコードが有効ではありません。::機能

class A 
    { 
     //error: 'B' was not declared in this scope 
     std::function<decltype(B)(int)> initB = [this](int value) 
               {decltype(B) temp; 
               temp.setValue(value); 
               return temp;}; 
     class 
     { 
     public: 
      void setValue(int val) {i=val;} 
     private: 
      int i; 
     } B = initB(10); 
    } 

私はstd::functionstaticを作るために作ってみました、そして、そのようなコードは動作しますが、STD ::機能がnon-trivial destructor持っているので、non-constexpr/constメンバーを必要とする - 悪いです、そのため、そのようなファイルを作成する必要があるソースファイルが必要です。これは、私の美しいヘッダー専用クラス階層のいくつかの退屈さと破壊を必要とします! (私は、怠け者で、ヘッダーにこの変数を定義することができますが、多重定義の問題が発生します)。私はそれが悪い設計かもしれないことを知っている(私は物事をテストしている)が、ソースファイルを関与せずにどのように問題を解決することができますか?

+1

ネストしたクラスを前方宣言することができます。したがって、クラスに名前を付けることができ、データメンバで 'decltype'を使う代わりにクラスを参照することができます。または、ネストされたクラスとデータメンバーの定義を完全に分離します。私は、このマージがあなたを買うものについて確信しています。 –

+0

@Johannes Schaub私はそれを見るので、私はなぜそれを匿名にしたかったのか分かりません。応答ありがとう:) – xinaiz

答えて

1

あなたの例が不自然ではあるが、同様の方法で、複雑なオブジェクトを初期化する私は必要な(あるいはその方が便利)きた時間があります。

しかし、なぜstd :: function <>を使用しますか?なぜ関数を使うだけではないのですか?

しかし、私は通常decltype(B)を使用しません。私はクラスに名前を付けるだけです。

+0

initBは、関数ptrのように、他のstd :: function <...>(ユーザー提供のものも含む)に再割り当てできる可能性がありますか? – lorro

+0

@lorro:しかしこの場合、initBとBの両方がAの構築中に初期化されるので、std :: function <>を使う利点はありません。 initBが静的であった場合、理論的にはAの新しいインスタンスの構築に影響を与えるために新しい値が割り当てられる可能性がある(すなわち、initBはBのインスタンスを構築するために使用されるファクトリである)ため、異なるであろう。 – Steven

0

私は何とか自分の意図を覆しているように感じますが、コンストラクタ内の変数を初期化すると、動作させることができます。

#include <functional> 

class A 
{ 
    class 
    { 
    public: 
    void setValue(int val) {i=val;} 
    private: 
    int i; 
    } B; 

    std::function<decltype(B)(int)> initB; 

public: 
    A() { 
    initB = [this](int value) 
      {decltype(B) temp; 
      temp.setValue(value); 
      return temp;}; 
    B = initB(10); 
    } 
}; 

int main() { 
    A a; 
} 
0

A :: initBは値です。メンバーフィールドを指定した順番で初期化が行われるため(ルーズに話す)、呼び出す場所では初期化されません。

#include <iostream> 
#include <functional> 
using namespace std; 

template<typename T, typename U> 
T set(T& tgt, const U& src) 
{ 
    new(&tgt) T(src); 
    return tgt; 
} 

class A 
{ 
    class 
    { 
    public: 
     void setValue(int val) {i=val;} 
    private: 
     int i; 
    } B = set(initB, [this](int value) 
         {decltype(B) temp; 
         temp.setValue(value); 
         return temp;})(10); 

    std::function<decltype(B)(int)> initB; 
}; 


int main() { 
    A a; 
} 
関連する問題