BREW vector(3)

昨日の
プログラムの、どこが問題だったかというと、

_Ufill( v._First , _N , _V );

この部分です。
この関数の実装は、

void _Ufill( iterator _F , size_type _N , const _Ty &_X ){
    for( ; 0 < _N ; --_N , ++_F ){
        // allocatorは使用しない
        // allocator.construct( _F , _X );
        operator new( (void*)_F ) _Ty( _X );
    }
}

こうなっています。
_Ufillの内部で、コピーコンストラクタを実行しているわけです。
なので、当然コンパイラは、どの型のコピーコンストラクタを実行するか、というのを知っている必要があるのですが、vector_proxyはvoid*型のメンバしか持っていないため、うまく動作しません。
そこで、仮想関数を使って実装することを考えてみます。
まず、

class functor_base{
public:
    virtual void operator()() = 0;
};

functorの仮想関数を作っておいて、型に依存する関数を、テンプレートクラスとして実装します。

template< class _Ty >
class _Ufill_functor : public functor_base{
public:
    _Ufill_functor( _Ty*& _P , size_t& _N , const _Ty& _X )
        : P( _P ) , N( _N ) , X( _X ){}
    void operator()(){
        _Ty* P_ = P;
        for( ; 0 < N ; --N , ++P_ ){
            new( P_ ) _Ty( X );
        }
    }
private:
    _Ty*&       P;
    size_t&     N;
    const _Ty&  X;
};

値渡しだと、functorを作成した瞬間に値が束縛されてしまい、まだ値が入っていないオブジェクトに対してfunctorを実行してしまうので、参照渡しにしています。
こうすれば、実行した瞬間の値が適用されることになります。
で、委譲する側は、functorを作って、それをvector_helperに渡し、委譲される側はいつものように実行するだけです。
あと、functorは参照渡しかポインタ渡しにしないと、スライシングが発生するので注意です。

explicit vector( size_type _N , const _Ty& _V = _Ty() ){
    functor_base& _Ufill =
        _Ufill_functor< _Ty >( _First , _N , _V );
    vector_helper::constructor(
        *(vector_proxy*)this ,
        sizeof( _Ty ) ,
        _N ,
        _Ufill
    );
}
class vector_helper{
    static void constructor(
        vector_proxy& v ,
        size_type n ,
        size_type _N ,
        functor_base& _Ufill
    ){
        v._First = _allocate( n , _N );
        // functor実行
        // 引数は内部に保持している
        _Ufill();
        v._Last = (void*)((byte*)v._First + n * _N);
        v._End = v._Last;
    }
};

出来たヽ(´ー`)ノ



……ええ、出来ました。出来たんですよ、確かに。
(面倒ですが)この方法で全てのメソッドを実装することが可能です。


しかし!





逆に容量増えます


もうこれは笑うしかないね(´▽`*)アハハ
ぶっちゃけ作ってるときは気が付きませんでした(;´Д`)


数時間掛けて作ったプログラムがゴミ箱行き……あゝ無情……。


ということで、別の方法を考えることになります。