#include #include #include #include #include #include using namespace std; #ifndef CPP11 #define nullptr NULL #endif template class arrayset { public: arrayset() : value() { ismem = false; child = nullptr; sibling = nullptr; numconstr++; } ~arrayset() { if (child!=nullptr) delete child; if (sibling!=nullptr) delete sibling; numdestr++; } arrayset(const arrayset &s) : value(s.value) { ismem = s.ismem; if (s.child==nullptr) child=nullptr; else child = new arrayset(*(s.child)); if (s.sibling==nullptr) sibling=nullptr; else sibling = new arrayset(*(s.sibling)); numcpy++; } arrayset(arrayset &&s) : value(std::move(s.value)) { ismem = s.ismem; child = s.child; sibling = s.sibling; s.child = nullptr; s.sibling = nullptr; nummove++; } arrayset &operator==(const arrayset &s) { if (this==&s) return *this; if (child!=nullptr) delete child; if (sibling!=nullptr) delete sibling; ismem = s.ismem; value = s.value; if (s.child==nullptr) child=nullptr; else child = new arrayset(*(s.child)); if (s.sibling==nullptr) sibling=nullptr; else sibling = new arrayset(*(s.sibling)); numassign++; } arrayset &operator==(arrayset &&s) { if (this==&s) return *this; ismem = s.ismem; value = std::move(s.value); if (child!=nullptr) delete child; child = s.child; s.child = nullptr; if (sibling!=nullptr) delete sibling; sibling = s.sibling; s.sibling = nullptr; nummassign++; } template bool ismember(const It &begin, const It &end) const { if (begin==end) return ismem; if (*begin == value) return child != nullptr && child->ismember(begin+1,end); return sibling != nullptr && sibling->ismember(begin,end); } template bool addmember(const It &begin, const It &end) { if (begin==end) { bool ret = !ismem; ismem = true; return ret; } else if (*begin==value) { if (child==nullptr) { child = new arrayset(); child->value = *(begin+1); } return child->addmember(begin+1,end); } else { if (sibling==nullptr) { sibling = new arrayset(); sibling->value = *begin; } return sibling->addmember(begin,end); } } static int numconstr,numdestr,numcpy,numassign,nummove,nummassign; private: arrayset *sibling; arrayset *child; char value; bool ismem; }; template<> int arrayset::numconstr = 0; template<> int arrayset::numdestr = 0; template<> int arrayset::numcpy = 0; template<> int arrayset::numassign = 0; template<> int arrayset::nummove = 0; template<> int arrayset::nummassign = 0; // I'm ignoring that the traits or allocator might be non-default template class stringset : public arrayset { public: typedef std::basic_string str; // can remove all of these... they are all the default /* stringset() : arrayset() { } ~stringset() { } stringset(const stringset &s) : arrayset(s) { } stringset(stringset &&s) : arrayset(std::move(s)) { } stringset &operator=(const stringset &s) { if (this==&s) return *this; arrayset::operator=(s); return *this; } stringset &operator=(stringset &&s) { if (this==&s) return *this; arrayset::operator=(std::move(s)); return *this; } */ bool ismember(const str &s) const { return arrayset::ismember(s.begin(),s.end()); } bool addmember(const str &s) { bool ret = arrayset::addmember(s.begin(),s.end()); if (ret) size++; return ret; } // NEW: void addlist(initializer_list l) { for(auto s : l) addmember(s); } int numwords() const { return size; } stringset() : arrayset() { size = 0; } stringset(const vector &v) // build from list : stringset() { // delegate to the other constructor first // cannot do anything else in this initialization list // (like initialize the base class) for(auto && s : v) addmember(s); } // NEW initializer list constructor: stringset(std::initializer_list strs) : stringset() { // delegate for(auto s : strs) addmember(s); } private: //int size = 0; int size; }; stringset loaddictionary(const char *filename) { ifstream f(filename); if (!f.good()) { // should throw exception... // but returning something here prevents RVO in g++ return stringset (); } stringset ret; while(!f.eof()) { string s; f >> s; if (s.size()>0) ret.addmember(s); } return ret; } int main(int argc, char **argv) { { stringset s = loaddictionary(argc>1 ? argv[0] : "words"); cout << "bubble? " << s.ismember("bubble") << endl; cout << "downtime? " << s.ismember("downtime") << endl; cout << "existentialism? " << s.ismember("existentialism") << endl; cout << "gobbledygook? " << s.ismember("gobbledygook") << endl; cout << "gobbledygoo? " << s.ismember("gobbledygoo") << endl; cout << "foo? " << s.ismember("foo") << endl; cout << "qwesr? " << s.ismember("qwesr") << endl; cout << "total of " << s.numwords() << " words" << endl; } { stringset s {"one","two","three","many","none"}; s.addlist({"five","six","seven"}); cout << "none? " << s.ismember("none") << endl; cout << "five?" << s.ismember("five") << endl; cout << "total of " << s.numwords() << " words" << endl; } cout << "-------------------------" << endl; cout << "# constructors: " << arrayset::numconstr << endl; cout << "# destructors: " << arrayset::numdestr << endl; cout << "# copies: " << arrayset::numcpy << endl; cout << "# assignments: " << arrayset::numassign << endl; cout << "# moves: " << arrayset::nummove << endl; cout << "# m-assigns: " << arrayset::nummassign << endl; return 0; }