2012-09-28

SCIP in C++11 ― 3.3.2節その2


キューのメッセージパッシング手続き実装と問題3.22

C++11でキューのデータの実体オブジェクトfrontPointerを、
makeQueue内で定義すると、frontPointerを各クロージャで共有するためには、
クロージャでfrontPointerを参照キャプチャしなければいけないが、
makeQueueが終了すると本体の寿命が尽きて、クロージャ内の参照も全部死ぬ。

そこでmakeQueueではfrontPointerの初期値を設定するのみにし、
frontPointerをスタックに入れて右辺値参照で保持するようにした。ああ面倒。
しかも右辺値参照だとなぜ保持できてるのかわからない。
仕様なのか実装系依存なのか。気持ち悪い。

デックはあまり興味ないので問題3.23はパス。
普通はデキューでなくデックじゃないかと思うがまあいいや。

----
typedef function<List(List)> Queue;

const Queue makeQueueDispatch(const List& initial)
{
    const List&& frontPointer(std::move(initial));

    const function<bool(void)> isEmptyQueue
        =[frontPointer](void){return(isNull(frontPointer));};

    const function<List(void)> frontQueue
        =[frontPointer,isEmptyQueue](void){
        if(isEmptyQueue()){
            cerr<<"FRONT called with an empty queue "<<listString(frontPointer)<<endl;
            exit(1);
            return(makeList());
        }
        return(car(frontPointer));
    };

    const function<void(List)> setfFrontPointer
        =[frontPointer](const List& item)
        {setfCar(frontPointer,item);};

    const function<List(List)> insertfQueue
        =[frontPointer,isEmptyQueue,setfFrontPointer]
        (const List& item)
        {
            if(isEmptyQueue()){
                setfFrontPointer(item);
            }else{
                appendf(frontPointer,makeList(item));
            }
            return(frontPointer);
        };

    const function<List(void)> deletefQueue
        =[frontPointer,isEmptyQueue](void)
        {
            if(isEmptyQueue()){
                cerr<<"DELETE! called with an empty queue "<<listString(frontPointer)<<endl;
                exit(1);
                return(makeList());
            }
            setf(cdr(frontPointer),frontPointer);
            return(frontPointer);
        };
   
    const function<List(void)> getQueue=[frontPointer](void)
        {return(frontPointer);};
   
    const Queue dispatch
        =[isEmptyQueue,frontQueue,insertfQueue,deletefQueue,getQueue]
        (const List& message){
        if(isEq(message,makeLeaf("empty-queue?"))){return(makeLeaf(isEmptyQueue));}
        if(isEq(message,makeLeaf("front-queue"))){return(makeLeaf(frontQueue));}
        if(isEq(message,makeLeaf("insert-queue!"))){return(makeLeaf(insertfQueue));}
        if(isEq(message,makeLeaf("delete-queue!"))){return(makeLeaf(deletefQueue));}
        if(isEq(message,makeLeaf("get-queue"))){return(makeLeaf(getQueue));}
        cerr<<"Unknown request --- MAKE-QUEUE"<<endl;
        exit(1);
        return(makeList());
    };

    return(dispatch);
}

const Queue makeQueue(void)
{
    return(makeQueueDispatch(makeList()));
}


const bool isEmptyQueue(const Queue& queue)
{return(executable<bool>
        (queue(makeLeaf("empty-queue?")))());}

const List frontQueue(const Queue& queue)
{return(executable<List>
        (queue(makeLeaf("front-queue")))());}

const Queue insertfQueue(const Queue& queue, const List& item)
{
    executable<List,List>
        (queue(makeLeaf("insert-queue!")))(item);
    return(queue);
}

const Queue deletefQueue(const Queue& queue)
{
    executable<List>
        (queue(makeLeaf("delete-queue!")))();
    return(queue);
}

void printQueue(const Queue& queue)
{cout<<listString(executable<List>(queue(makeLeaf("get-queue")))());}

//---------abstraction barrier---------
int main(int argc, char** argv)
{

    cout<<"Excersize 3.22:"<<endl;
    const auto q1(makeQueue());
    printQueue(q1);cout<<endl;
    printQueue(insertfQueue(q1,makeLeaf("a")));cout<<endl;
    printQueue(insertfQueue(q1,makeLeaf("b")));cout<<endl;
    printQueue(insertfQueue(q1,makeLeaf("c")));cout<<endl;
    printQueue(deletefQueue(q1));cout<<endl;
    printQueue(deletefQueue(q1));cout<<endl;
    printQueue(insertfQueue(q1,makeLeaf("d")));cout<<endl;
    printQueue(deletefQueue(q1));cout<<endl;
    printQueue(deletefQueue(q1));cout<<endl;

    return(0);
}
----
出力
----
Excersize 3.22:
()
('a)
('a 'b)
('a 'b 'c)
('b 'c)
('c)
('c 'd)
('d)
()

0 件のコメント :

コメントを投稿