Как перегрузить ostream_iterator шаблонным пользовательским контейнером?

#c #templates #iterator

#c #шаблоны #итератор

Вопрос:

Как мне объявить и написать ostream_iterator для использования с моей программой

Моя цель — вызвать следующие функции с моим контейнером и типом данных:

 transform(myList.begin(), myList.end(), ostream_iterator<string> (cout), appendSpace);

copy(myList.begin(), myList.end(), ostream_iterator<string> (cout, ' '));
 

У меня есть пользовательский класс string с именем BLString, который действует как обычный класс string .
У меня есть пользовательский класс списка с именем DblLinkedList, который представляет собой двусвязный список, такой же, как список STL.

Я превратил DblLinkedList в форму шаблона и добавил пользовательский встроенный класс итератора.

Я опустил некоторые файлы из соображений простоты, могу включить при необходимости.

Код приведен ниже:

 ////
///  DblLinkedList.h
////

#ifndef DblLinkedList_h
#define DblLinkedList_h

#include "BLString.h"
#include <iterator>

using namespace std;


// Node class creates containers for linked list
template<typename type>
class Node {   // fully defined here due to its simplicity
    
    public:
    Node() {
        next = prev = nullptr;
    }
    Node(type str) {
        data = str;
        next = prev = nullptr;
    }
    type data;
    Node *next;
    Node *prev;
};

//DblLinkedList class links together Node class objects
template<typename type>
class DblLinkedList {
  public:
    class Iterator{
        Node<type>* it;
    public:
        Iterator(Node<type> *itArg){it = itArg;}
        void operator   (){it = it->next;}
        void operator   (int){it = it->next;}
        void operator --(){it = it->prev;}
        type operator *(){return it->data;}
        bool operator == (Iterator itArg){return (it == itArg);}
        bool operator != (Iterator itArg){return (it != itArg);}
        //FIXME: write this instead of overloading ostream_iterator class?
        //Iterator(ostreamamp; ostr){ostr << it->data;}
    };
    //FIXME: possible to overload class to make usable with copy() and transform() ?
/*
    template<typename Type>
    class ostream_iterator{
    public:
        ostream_iterator<Type> (ostreamamp; ostrm){
            ostrm << *(Iterator::it->data);
        }
    };
*/
    
    Iterator begin(){return Iterator(head);}
    Iterator end(){return Iterator(tail);}
    //default constructor
    DblLinkedList();
    //copy constructor
    DblLinkedList(const DblLinkedList amp;dll);
    //assingment operator
    DblLinkedList operator=(const DblLinkedList amp;dll);
    //destructor
    ~DblLinkedList();
    //insertion operator
    //friend ostreamamp; operator<<(ostreamamp; ostrm, const DblLinkedList amp;dll);
    friend ostreamamp; operator<<(ostreamamp; ostrm, const DblLinkedList amp;dll){
        dll.resetIterator();
        while(dll.it){
            ostrm << dll.next() << " ";
        }
        return ostrm;
    }
    //insert
    bool insert(const type amp;str);
    //remove
    bool remove(const type amp;str);
    //remove last
    bool pop_back();
    // resets iterator
    void resetIterator() const;
    // has more
    bool hasMore() const;
    // next string
    type next() const;
    // test connections
    void testConnections();
    // list size
    int getCount() const;
    // for testing
    static int getCreatedNodes();
    // for testing
    static int getCurrentNodes();
  private:
    Node<type> *head, *tail;
    // mutable says that it can change in a const member function
    mutable Node<type> *it;
    int count;
    static int currentNodes, createdNodes;
};

// for testing
template<typename type>
int DblLinkedList<type>::createdNodes = 0;
// for testing
template<typename type>
int DblLinkedList<type>::currentNodes = 0;
// for testing
template<typename type>
int DblLinkedList<type>::getCreatedNodes(){return createdNodes;}
// for testing
template<typename type>
int DblLinkedList<type>::getCurrentNodes(){return currentNodes;}
// Default constructor
template<typename type>
DblLinkedList<type>::DblLinkedList() {
    head = nullptr;
    tail = nullptr;
    it = nullptr;
    count = 0;
}

// copy constructor
template<typename type>
DblLinkedList<type>::DblLinkedList(const DblLinkedList amp;dll){
    head = nullptr;
    tail = nullptr;
    it = nullptr;
    count = 0;
    // if copying empty list
    if(!dll.head)
        head = tail = nullptr;
    // if copying list with 1 or more items
    else{
        dll.resetIterator();
        while(dll.hasMore()){
            Node<type>* temp = new Node<type>(dll.it->data);
            createdNodes  ;// for testing
            currentNodes  ;// for testing
            //if copying list with 1 item or 1st item
            if(!head){
                head = tail = temp;
                count  ;
            //if copying list with more than 1 item
            }else{//adding to back of list
                temp->prev = tail;
                tail->next = temp;
                tail = temp;
                count  ;
            }
            dll.it = dll.it->next;
        }
    }
}
// Assingment operator
template<typename type>
DblLinkedList<type> DblLinkedList<type>::operator=(const DblLinkedList amp;dll){
    if(this != amp;dll){// self assignment check
        resetIterator();
        while(hasMore()){
            head = it->next;
            currentNodes--;// for testing
            delete it;
            it = head;
        }
        head = nullptr;
        tail = nullptr;
        it = nullptr;
        count = 0;
        dll.resetIterator();
        // if copying empty list
        if(!dll.head)
            head = tail = nullptr;
        //if copying list with 1 or more items
        while(dll.hasMore()){
            Node<type>* temp = new Node<type>(dll.it->data);
            createdNodes  ;// for testing
            currentNodes  ;// for testing
            // if copying list with 1 item
            if(!head){
                head = tail = temp;
                count  ;
            //if copying list with more than 1 item
            }else{
                temp->prev = tail;
                tail->next = temp;
                tail = temp;
                count  ;
            }
            dll.it = dll.it->next;
        }
    }
    return *this;
}
//destructor
template<typename type>
DblLinkedList<type>::~DblLinkedList(){
    resetIterator();
    while(hasMore()){
        head = it->next;
        delete it;
        currentNodes--;// for testing
        it = head;
    }
}

// instertion operator
//template<typename type> // move inside

//insert
template<typename type>
bool DblLinkedList<type>::insert(const type amp;str){
    bool inserted = false;
    //if instering in blank list
    if(!head){
        Node<type> *temp = new Node<type>(str);
        createdNodes  ;// for testing
        currentNodes  ;// for testing
        head = tail = temp;
        inserted = true;
        count  ;
    }
    //  if inserting to front
    else if((str < head->data)){
        Node<type> *temp = new Node<type>(str);
        createdNodes  ;// for testing
        currentNodes  ;// for testing
        head->prev = temp;
        temp->next = head;
        head = temp;
        inserted = true;
        count  ;
    }
    // if inserting at end
    else if(str > tail->data){
        Node<type> *temp = new Node<type>(str);
        createdNodes  ;// for testing
        currentNodes  ;// for testing
        tail->next = temp;
        temp->prev = tail;
        tail = temp;
        inserted = true;
        count  ;
    }
    // if inserting inside
    else{
        resetIterator();
        while(it){
            //alphebetical placement qualifier
            //does not enter statment if word already exists in list
            if ((str < it->data) amp;amp; (str > it->prev->data)){
                Node<type> *temp = new Node<type>(str);
                createdNodes  ;// for testing
                currentNodes  ;// for testing
                it->prev->next = temp;
                temp->prev = it->prev;
                temp->next = it;
                it->prev = temp;
                inserted = true;
                count  ;
                break;
            }
        it = it->next;
        }
        
    }
    return inserted;
}
//remove
template<typename type>
bool DblLinkedList<type>::remove(const type amp;str){
    bool removed = false;
    //if list is not empty
    if(head){
        // if removing head
        if(str == head->data){
            head->next->prev = nullptr;
            it = head;
            head = head->next;
            currentNodes--;// for testing
            delete it;
            removed = true;
            count--;
        }
        //if removing tail
        else if(str == tail->data){
            tail->prev->next = nullptr;
            it = tail;
            tail = tail->prev;
            currentNodes--;// for testing
            delete it;
            removed = true;
            count--;
        //if removing inside
        }else{
            resetIterator();
            while(it){
                if(str == it->data){
                    it->prev->next = it->next;
                    it->next->prev = it->prev;
                    currentNodes--;// for testing
                    delete it;
                    removed = true;
                    count--;
                    break;
                }
                it = it->next;
            }
        }
    }
    return removed;
}
template<typename type>
bool DblLinkedList<type>::pop_back(){
    it = tail;
    tail->prev->next = nullptr;
    tail = tail->prev;
    delete it;
    currentNodes--;
    count--;
    return true;
}
// reset iterator
template<typename type>
void DblLinkedList<type>::resetIterator() const{
    if(head)
        it = head;
    else
        it = nullptr;
}
// has more
template<typename type>
bool DblLinkedList<type>::hasMore() const{
    bool tempBool = false;
    if(it)
        return true;
    return tempBool;
}
// next
template<typename type>
type DblLinkedList<type>::next() const{
    type tempData;//possible ineficiency source
    tempData = it->data;
    it = it->next;
    return tempData;
}
// for testing
template<typename type>
void DblLinkedList<type>::testConnections(){
    if(head->prev == nullptr){
        cout << "head->data --- " << head->data << endl;
        cout << "head->prev == nullptr ----- PASSED" << endl;
    }
    if(tail->next == nullptr){
        cout << "tail->data --- " << tail->data << endl;
        cout << "tail->next == nullptr ----- PASSED" << endl;
    }
    
    resetIterator();
    while(hasMore()){
        if(it != tail){
        if(it == it -> next -> prev)
            cout << "(it != it -> next -> prev) ---- PASSED" << endl;
        }
        it = it->next;
    }
}
// getCount
template<typename type>
int DblLinkedList<type>::getCount() const {return count;}


#endif /* DblLinkedList_h */

 
 ////
/// main.cpp
////


// #include "pch.h"   // didn't need this
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <string>//need because fin doesn't accept BLString
#include "BLString.h"
#include "DblLinkedList.h"
using namespace std;

template<typename type>
void advanceIterator(typename DblLinkedList<type>::Iterator amp;it_Name, unsigned int n){
    for(int i = 0; i < n;   i)
        it_Name  ;
}
template<typename type>
type addSpace(type data);
//changer function per specs
template<typename type>
void changer(DblLinkedList<type> dll);
//print lists
template<typename type>
void printListSizes(const DblLinkedList<type> amp;list1, const DblLinkedList<type> amp;list2, const DblLinkedList<type> amp;modList1, const DblLinkedList<type> amp;modList2);
//read from file to list
template<typename type>
void fileToList(DblLinkedList<type> amp;dll, string fileName);
//print from list to file
template<typename type>
void listToFile(DblLinkedList<type> amp;dll, string fileName);
//remove from modList all of the strings stored in list
template<typename type>
void removeFrom(DblLinkedList<type> amp;modList, DblLinkedList<type> amp;list);

int main() {
    
    DblLinkedList<BLString> list1;
    string fileName;

    //reading from infile1.txt into list 1
    fileName = "infile1.txt";
    fileToList(list1, fileName);
    
    cout << endl;

    cout << "list1: ";
    auto it = list1.begin(); //DblLinkedList<BLString>::Iterator it = list1.begin();
    for(int i = 0; i < 5;   i){
        cout << * it << " ";
           it;
    }
    
    /* FIXME: not working; need to write overloaded class in DblLinkedList.h */
    //copy(it, it_3, ostream_iterator<BLString>(cout));
     
    cout << endl;
    
}

template<typename type>
void changer(DblLinkedList<type> dll){
    dll.insert("ZIP");
    dll.insert("ZAP");
    cout << "Inside changer. Size of list: "<< dll.getCount() << endl;
}
template<typename type>
void printListSizes(const DblLinkedList<type> amp;list1, const DblLinkedList<type> amp;list2, const DblLinkedList<type> amp;modList1, const DblLinkedList<type> amp;modList2) {
    cout << endl;
    cout << "List sizes" << endl;
    cout << "--------------" << endl;
    cout << left << setw(10) <<"list1 "  << right << list1.getCount() << endl;
    cout << left << setw(10) <<"list2 "  << right << list2.getCount() << endl;
    cout << left << setw(10) <<"modList1 "  << right << modList1.getCount() << endl;
    cout << left << setw(10) << "modList2 " << right << modList2.getCount() << endl;
}
template<typename type>
void fileToList(DblLinkedList<type> amp;dll, string fileName){
    ifstream fin(fileName);
    type word;
    while(!fin.eof()){
        fin >> word;
        dll.insert(word);
    }
    fin.close();
}
template<typename type>
void listToFile(DblLinkedList<type> amp;dll, string fileName){
    ofstream fout(fileName);
    fout << dll;
    fout.close();
}
template<typename type>
void removeFrom(DblLinkedList<type> amp;modList, DblLinkedList<type> amp;list){
    list.resetIterator();
    while(list.hasMore())
        modList.remove(list.next());
}
//FIXME: not completed
template<typename type>
type addSpace(type data){
    return data   " ";
}

 

infile1.txt содержит главу из книги; просто набор слов для тестирования программы.

Пример:

Эти беспорядочные, возбужденные группы состояли в основном из мужчин с зелеными ветками на шляпах и самым нелепым оружием в руках. Некоторые, правда, держали на плечах охотничьи ружья, а кое-где размахивали мечами; но большинство из них были вооружены дубинками, и большинство из них тащили за собой гигантские пики, сделанные из кос, столь же грозные на вид, сколь и неуклюжие в руке. Среди этих импровизированных военных были ткачи, пивовары, плотники, кузнецы, каменщики, сапожники и представители всех других мирных профессий. Бриджуотер, как и Тонтон, так щедро пожертвовал своей мужественностью на службу герцогу-бастарду, что для любого, кто воздержался, чей возраст и сила допускали его ношение оружия, означало заклеймить себя трусом или папистом.