2013-06-09 5 views
17

私のTimerオブジェクトをTimer :: create()だけで作成します。この目的のために、私はコンストラクタを非公開にしました。しかし、私は、コンパイラのエラーは、 "Timer :: Timer(unsigned int) 'がnew_allocator.hのコンテキスト内でprivateであるというエラーが出ます。どうすればこの問題を解決できますか?最も簡単な解決策は、それ自体に再バインドするrebindを再実装std::allocator<Timer>から派生することになるので、vectorは再バインドできませんでしプライベートコンストラクタを持つオブジェクトのvector :: emplace_back

class Timer { 

    struct TimerAllocator: std::allocator<Timer> 
    { 
     template< class U, class... Args > 
     void construct(U* p, Args&&... args) 
     { 
      ::new((void *)p) U(std::forward<Args>(args)...); 
     } 

     template< class U > struct rebind { typedef TimerAllocator other; }; 

    }; 
    friend class TimerAllocator; 

    private: 
     int timeLeft; 

    Timer(unsigned int ms) : timeLeft(ms) 
    {} 

    public: 
     static std::vector<Timer, TimerAllocator> instances; 
     static void create(unsigned int ms) { 
      instances.emplace_back(ms); 
     } 
}; 

std::vector<Timer, Timer::TimerAllocator> Timer::instances; 

int main() 

{ 
    Timer::create(100); 
} 

class Timer { 
    private: 
     int timeLeft; 
     Timer(unsigned int ms) : timeLeft(ms) {} 

    public: 
     static std::vector<Timer> instances; 
     static void create(unsigned int ms) { 
      instances.emplace_back(ms); 
     } 
}; 

std::vector<Timer> Timer::instances; 
+1

、唯一の理由は、 'コピー/移動コンストラクタが公開されているので、うまくいくpush_back'です。すべてのコンストラクタがprivateであれば、 'emplace_back'も' push_back'も動作しません。 – hvd

答えて

13

おそらく、タイマーに友人になり、独自のアロケータを実装する必要がありますアロケータをstd::allocatorに戻し、実際にTimerを作成するために自分自身のconstructを実装します。

+0

...または 'std :: vector 'をあなたのクラスの 'friend'にすることができます。きれいではないがはるかに単純です。 –

+6

@ KonradRudolph、それほど単純ではありません:もちろん、私はそれがうまくいけばベクトルフレンドを作る助言をしますが、そのことはベクトル_はコンストラクタを呼び出さない、アロケータdoes_です。ベクトルの友人を作ることは助けにならないでしょう。 – Lol4t0

+0

ああ、当然のことです。私はちょうど別の答えでこれをお勧めしました( 'std :: deque'を使って)*働いていましたが、今はなぜ*実際に動作するのか分かりません。 –

9

特別なvectorアロケータを持つ必要がないように、友人移転のセマンティクスを使用できます。それは、友情の依存性注入のようなものです。これは本当に簡単です。自分自身をクラスの友人にする空のクラスを作成します。しかし、デフォルトのコンストラクタはprivateなので、クラスだけがインスタンスを作成できます。しかしクラスはまだコピー可能なので、誰にも渡すことができます。

あなたのTimerコンストラクタはパブリックになりますが、これらのオブジェクトのいずれかを引数として必要とします。したがって、あなたのクラスまたはそれによって呼び出される関数だけがこれらのオブジェクトを直接作成できます(コピー/移動は引き続き機能します)。ここで

はあなたのコード(live example)でそれを行うことができる方法です:もちろん

class TimerFriend 
{ 
public: 
    TimerFriend(const TimerFriend&) = default; 
    TimerFriend& operator =(const TimerFriend&) = default; 

private: 
    TimerFriend() {} 

    friend class Timer; 
} 

class Timer { 
    private: 
     int timeLeft; 

    public: 
     Timer(unsigned int ms, const TimerFriend&) : timeLeft(ms) {} 

     static std::vector<Timer> instances; 
     static void create(unsigned int ms) { 
      instances.emplace_back(ms, TimerFriend()); 
     } 
}; 

std::vector<Timer> Timer::instances; 
関連する問題