[
  {
    "path": ".gitignore",
    "content": "# Mac OS\n.DS_Store\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n*.dll\n\n# Fortran module files\n*.mod\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n*.lib\n\n# Executables\n*.exe\n*.out\n*.app\n\n# ctags\n*tags*\n\n# vim\n*.swp\n"
  },
  {
    "path": ".tools/dir_handler.rb",
    "content": "class DirHandler\n  attr_reader :paths\n\n  def initialize dir, extension\n    @paths = list_paths_recursively dir, extension\n  end\n\n  def on_each_line!\n    @paths.each do |path|\n      content = File.readlines path\n      content.each { |line| yield line }\n      write_back path, content \n    end\n  end  \n\nprivate\n  def list_paths_recursively dir, extension\n    Dir.glob \"#{ dir }/**/*.#{ extension }\"\n  end\n\n  def write_back filename, content\n    File.open(filename, 'w+'){ |file| file.puts content }\n  end\nend\n"
  },
  {
    "path": ".tools/format.rb",
    "content": "require_relative 'dir_handler'\n\nclass Format\n  attr_reader :dir, :extensions\n\n  def initialize dir, extensions\n    @dir = dir\n    @extensions = extensions\n    @dir.freeze\n    @extensions.freeze\n    @handlers = extensions.collect{ |e| DirHandler.new dir, e }\n  end\n\n  # 1,2,3,4  => 1, 2, 3, 4\n  def for_commas\n    each_line! do |line|   \n      begin\n        line.gsub! /,(\\S)/, ', \\1' unless line.match /.*\\\".*,.*\\\".*/ or line.match /','/\n      rescue Exception => e\n        puts e.message + \", ignored.\"\n      end\n    end\n  end \n \n  #{foo} => { foo }\n  def for_curly_brackets\n    for_pairs '{', '}'\n  end\n \n  private\n  def each_line!\n    @handlers.each do |h|\n      h.on_each_line! { |line| yield line }\n    end\n  end\n\n  def for_pairs open, close\n    each_line! do |line|\n      begin \n        if line.match /#{ open + \".*\" + close }/ \n          line.gsub! /#{ open   + \"(\\S)\"}/,   open + ' \\1'\n          line.gsub! /#{ \"(\\S)\" + close }/,   '\\1 '+ close\n        end\n      rescue Exception => e\n        puts e.message + \", ignored.\"\n      end\n    end\n  end\nend    \n\nformat = Format.new ARGV[0], [ \"cpp\", \"h\", \"hpp\", \"md\" ]\nformat.for_commas\nformat.for_curly_brackets\n"
  },
  {
    "path": ".tools/insert_space_in_include.rb",
    "content": "# Yue Wang Aug.2015\n# change #include<iostream> to #include <iostream>\n# to use\n#   $ ruby insert_space_in_include.rb dir extension\n\nif ARGV.size != 2\n  puts \"wrong argumens\"\n  exit\nend\n\ndir = ARGV[0]\nextension = ARGV[1]\n\npaths = Dir.glob \"#{ dir }/**/*.#{ extension }\"\npaths.each do |path|\n  content = File.readlines path\n  content.each do |line|\n    #check if it's something like \"#include<iostream>\"\n    if line.include?('#') and line.split(' ').size == 1\n      line.sub! \"#include\", \"#include \"\n    end\n  end\n  File.open(path, 'w+'){ |file| file.puts content }\nend\n"
  },
  {
    "path": ".tools/remove_blank_tails.rb",
    "content": "#\n# @Yue Wang \n# Aug 2015\n# To use:\n#   $ ruby remove_blank_tails.rb dir extension\n#\n\nclass RemoveBlankTails\n\n  def initialize dir, extension\n    @paths = Dir.glob \"#{ dir }/**/*.#{ extension }\"\n  end\n\n  def perform\n    @paths.each do |path|\n      r = File.readlines(path).reverse\n      i = r.find_index \"}\\n\"\n      if i != 0 and !i.nil? \n        content = r.drop(i).reverse\n        File.open(path, 'w+'){ |file| file.puts content }\n        yield path,i if i != 0\n      end\n    end\n  end\n\nend\n\n\nif ARGV.size != 2\n  puts \"wrong argumens\"\n  exit\nend\n\nrbt = RemoveBlankTails.new ARGV[0], ARGV[1]\nrbt.perform do |path, count|\n  puts \"[#{ path  }] : deleted [#{ count }] lines \"\nend\n"
  },
  {
    "path": ".tools/remover.rb",
    "content": "# @Yue Wang  Aug 2015\n#\n# Recursively remove lines that contain some word from files within the given directory.\n# To use:\n#   $ ruby remover.rb dirname file_extension key_word\n# Insensitive casing by default.\n#\n\nclass Remover\n  attr_reader :matched, :unmatched\n  \n  def initialize\n    @matched = {}\n    @unmatched = {}\n  end\n\n  def perform_on filename\n    @filename = filename\n    \n    File.readlines(@filename).each_with_index do |line, i| \n      if yield line, i\n        @matched[ i + 1 ] = line\n      else\n        @unmatched[ i + 1 ] = line\n      end\n    end \n    \n    File.open(@filename, 'w+'){ |file| file.puts @unmatched.values }\n  end\n\nend\n\nif ARGV.size != 3\n  puts \"wrong agruments\"\n  exit\nend\n\ndir = ARGV[0]\nextension = ARGV[1]\nexpr = ARGV[2]\n \nallFilePaths = Dir.glob \"#{ dir }/**/*.#{ extension }\"\npattern = Regexp.new(Regexp.escape(expr), Regexp::IGNORECASE)\n\nallFilePaths.each do |path|\n \n  rm = Remover.new\n  rm.perform_on( path ) do |line, i| \n    begin\n      line.match(pattern)\n    rescue #to handl exception caused by say encoding\n      puts \"\\n---------------exception happens when reading the line:\"\n      puts line\n      puts \"file: [#{ path }] line:[#{ i }]\"\n      puts \"---------------just igonored\\n\" \n      result = false\n    end\n  end\n  \n  if !rm.matched.empty? \n    puts \"lines deleted in file [#{ path }] :\" \n  else\n    puts \"no matched found in file [#{ path }].\"  \n  end\n  \n  rm.matched.each do |idx, line|\n    puts \"[#{ idx  }] #{ line }\"\n  end\n\nend\n"
  },
  {
    "path": ".tools/test.txt",
    "content": "_23456789\n_bcdefghijk\n_----------\n_f\n_lse\n"
  },
  {
    "path": ".tools/uniform_comments_mark.rb",
    "content": "# Yue Wang  Aug.2015\n#   sub /// or //! to //\n#   to use:\n#     $ ruby uniform_comments_mark.rb dir extension\n\nif ARGV.size != 2\n  puts \"wrong argumens\"\n  exit\nend\n\ndir = ARGV[0]\nextension = ARGV[1]\n\npaths = Dir.glob \"#{ dir }/**/*.#{ extension }\"\npaths.each do |path|\n  content = File.readlines path\n  content.each do |line|\n    line.sub! \"///\", \"//\"\n    line.sub! \"//!\", \"//\"\n  end\n  File.open(path, 'w+'){ |file| file.puts content }\nend\n"
  },
  {
    "path": "LICENSE",
    "content": "CC0 1.0 Universal\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator and\nsubsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for the\npurpose of contributing to a commons of creative, cultural and scientific\nworks (\"Commons\") that the public can reliably and without fear of later\nclaims of infringement build upon, modify, incorporate in other works, reuse\nand redistribute as freely as possible in any form whatsoever and for any\npurposes, including without limitation commercial purposes. These owners may\ncontribute to the Commons to promote the ideal of a free culture and the\nfurther production of creative, cultural and scientific works, or to gain\nreputation or greater distribution for their Work in part through the use and\nefforts of others.\n\nFor these and/or other purposes and motivations, and without any expectation\nof additional consideration or compensation, the person associating CC0 with a\nWork (the \"Affirmer\"), to the extent that he or she is an owner of Copyright\nand Related Rights in the Work, voluntarily elects to apply CC0 to the Work\nand publicly distribute the Work under its terms, with knowledge of his or her\nCopyright and Related Rights in the Work and the meaning and intended legal\neffect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not limited\nto, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display, communicate,\n  and translate a Work;\n\n  ii. moral rights retained by the original author(s) and/or performer(s);\n\n  iii. publicity and privacy rights pertaining to a person's image or likeness\n  depicted in a Work;\n\n  iv. rights protecting against unfair competition in regards to a Work,\n  subject to the limitations in paragraph 4(a), below;\n\n  v. rights protecting the extraction, dissemination, use and reuse of data in\n  a Work;\n\n  vi. database rights (such as those arising under Directive 96/9/EC of the\n  European Parliament and of the Council of 11 March 1996 on the legal\n  protection of databases, and under any national implementation thereof,\n  including any amended or successor version of such directive); and\n\n  vii. other similar, equivalent or corresponding rights throughout the world\n  based on applicable law or treaty, and any national implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention of,\napplicable law, Affirmer hereby overtly, fully, permanently, irrevocably and\nunconditionally waives, abandons, and surrenders all of Affirmer's Copyright\nand Related Rights and associated claims and causes of action, whether now\nknown or unknown (including existing as well as future claims and causes of\naction), in the Work (i) in all territories worldwide, (ii) for the maximum\nduration provided by applicable law or treaty (including future time\nextensions), (iii) in any current or future medium and for any number of\ncopies, and (iv) for any purpose whatsoever, including without limitation\ncommercial, advertising or promotional purposes (the \"Waiver\"). Affirmer makes\nthe Waiver for the benefit of each member of the public at large and to the\ndetriment of Affirmer's heirs and successors, fully intending that such Waiver\nshall not be subject to revocation, rescission, cancellation, termination, or\nany other legal or equitable action to disrupt the quiet enjoyment of the Work\nby the public as contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason be\njudged legally invalid or ineffective under applicable law, then the Waiver\nshall be preserved to the maximum extent permitted taking into account\nAffirmer's express Statement of Purpose. In addition, to the extent the Waiver\nis so judged Affirmer hereby grants to each affected person a royalty-free,\nnon transferable, non sublicensable, non exclusive, irrevocable and\nunconditional license to exercise Affirmer's Copyright and Related Rights in\nthe Work (i) in all territories worldwide, (ii) for the maximum duration\nprovided by applicable law or treaty (including future time extensions), (iii)\nin any current or future medium and for any number of copies, and (iv) for any\npurpose whatsoever, including without limitation commercial, advertising or\npromotional purposes (the \"License\"). The License shall be deemed effective as\nof the date CC0 was applied by Affirmer to the Work. Should any part of the\nLicense for any reason be judged legally invalid or ineffective under\napplicable law, such partial invalidity or ineffectiveness shall not\ninvalidate the remainder of the License, and in such case Affirmer hereby\naffirms that he or she will not (i) exercise any of his or her remaining\nCopyright and Related Rights in the Work or (ii) assert any associated claims\nand causes of action with respect to the Work, in either case contrary to\nAffirmer's express Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n  a. No trademark or patent rights held by Affirmer are waived, abandoned,\n  surrendered, licensed or otherwise affected by this document.\n\n  b. Affirmer offers the Work as-is and makes no representations or warranties\n  of any kind concerning the Work, express, implied, statutory or otherwise,\n  including without limitation warranties of title, merchantability, fitness\n  for a particular purpose, non infringement, or the absence of latent or\n  other defects, accuracy, or the present or absence of errors, whether or not\n  discoverable, all to the greatest extent permissible under applicable law.\n\n  c. Affirmer disclaims responsibility for clearing rights of other persons\n  that may apply to the Work or any use thereof, including without limitation\n  any person's Copyright and Related Rights in the Work. Further, Affirmer\n  disclaims responsibility for obtaining any necessary consents, permissions\n  or other rights required for any use of the Work.\n\n  d. Affirmer understands and acknowledges that Creative Commons is not a\n  party to this document and has no duty or obligation with respect to this\n  CC0 or use of the Work.\n\nFor more information, please see\n<http://creativecommons.org/publicdomain/zero/1.0/>\n"
  },
  {
    "path": "README.md",
    "content": "## C++ Primer 5 Answers(C++11/14)\n\n[![GitHub issues](https://img.shields.io/github/issues/Mooophy/Cpp-Primer.svg)](https://github.com/Mooophy/Cpp-Primer/issues)\n[![GitHub license](https://img.shields.io/badge/license-CC0-blue.svg)](https://raw.githubusercontent.com/Mooophy/Cpp-Primer/master/LICENSE)\n[![](https://img.shields.io/badge/%E4%B8%AD%E6%96%87-%E8%AE%A8%E8%AE%BA%E5%8C%BA-yellowgreen.svg)](https://github.com/ReadingLab/Discussion-for-Cpp)\n[![](https://img.shields.io/badge/douban-%E5%B0%8F%E7%BB%84-green.svg)](http://www.douban.com/group/532124/)\n\n### Compilers recommended\n * Windows: Visual Studio 2015+ \n \n * Linux: g++ 5.0+     \n```\ng++ -std=c++14 some_ex.cpp -o some_ex\n```\n \n * Mac: clang++ 3.7+\n```\nclang++ -std=c++1y some_ex.cpp -o some_ex\n```\n\n### Contents\n\n- [Chapter 1. Getting Started](ch01/README.md)\n- Part I: The Basics\n  - [Chapter 2. Variables and Basic Types](ch02/README.md)\n  - [Chapter 3. Strings, Vectors, and Arrays](ch03/README.md)\n  - [Chapter 4. Expressions](ch04/README.md)\n  - [Chapter 5. Statements](ch05/README.md)\n  - [Chapter 6. Functions](ch06/README.md)\n  - [Chapter 7. Classes](ch07/README.md)\n- Part II: The C++ Library\n  - [Chapter 8. The IO Library](ch08/README.md)\n  - [Chapter 9. Sequential Containers](ch09/README.md)\n  - [Chapter 10. Generic Algorithms](ch10/README.md)\n  - [Chapter 11. Associative Containers](ch11/README.md)\n  - [Chapter 12. Dynamic Memory](ch12/README.md)\n- Part III: Tools for Class Authors\n  - [Chapter 13. Copy Control](ch13/README.md)\n  - [Chapter 14. Overloaded Operations and Conversions](ch14/README.md)\n  - [Chapter 15. Object-Oriented Programming](ch15/README.md)\n  - [Chapter 16. Templates and Generic Programming](ch16)\n- Part IV:  Advanced Topics\n  - [Chapter 17. Specialized Library Facilities](ch17)\n  - [Chapter 18. Tools for Large Programs](ch18)\n  - [Chapter 19. Specialized Tools and Techniques](ch19)\n"
  },
  {
    "path": "ch01/README.md",
    "content": "## Exercise 1.1\n\n> Review the documentation for your compiler and determine what file naming convention it uses. Compile and run the main program from page 2.\n\n * [GCC and File Extensions](http://labor-liber.org/en/gnu-linux/development/index.php?diapo=extensions) \n * [File Types Created for Visual C++ Projects](https://msdn.microsoft.com/en-us/library/3awe4781.aspx)\n\n## Exercise 1.2\n\n> Exercise 1.2: Change the program to return -1. A return value of -1 is often treated as an indicator that the program failed. Recompile and rerun your program to see how your system treats a failure indicator from main.\n\n### Windows\n\n![windows](https://db.tt/DIJd9eZb)\n\n### Linux\n\n![linux](https://db.tt/lhzXhpCt)\n\n**255**? why? please look at [this](http://www.tldp.org/LDP/abs/html/exitcodes.html)\n\n## Exercise 1.3\n> Write a program to print Hello, World on the standard output.\n\n```cpp\n#include <iostream>\n\nint main()\n{\n    std::cout << \"Hello, World\" << std::endl;\n    return 0;\n}\n```\n\n## Exercise 1.4\n> Our program used the addition operator, +, to add two numbers. Write a program that uses the multiplication operator, *, to print the product instead.\n\n```cpp\n#include <iostream>\n\nint main()\n{\n    std::cout << \"Enter two numbers:\" << std::endl;\n    int v1 = 0, v2 = 0;\n    std::cin >> v1 >> v2;\n    std::cout << \"The product is \" << v1 * v2 << std::endl;\n\n    return 0;\n}\n```\n\n## Exercise 1.5\n\n> We wrote the output in one large statement. Rewrite the program to use a separate statement to print each operand.\n\n```cpp\n#include <iostream>\n\nint main()\n{\n    std::cout << \"Enter two numbers:\" << std::endl;\n    int v1 = 0, v2 = 0;\n    std::cin >> v1 >> v2;\n    std::cout << \"The product of \";\n    std::cout << v1;\n    std::cout << \" and \";\n    std::cout << v2;\n    std::cout << \" is \";\n    std::cout << v1 * v2;\n    std::cout << std::endl;\n    return 0;\n}\n```\n\n## Exercise 1.6\n> Explain whether the following program fragment is legal.\n\nIt's illegal.\n\n**[Error] expected primary-expression before '<<' token**\n\nFixed it: remove the spare semicolons.\n\n```cpp\nstd::cout << \"The sum of \" << v1 << \" and \" << v2 << \" is \" << v1 + v2 << std::endl;\n```\n\n## Exercise 1.7\n\n> Compile a program that has incorrectly nested comments.\n\nExample:\n```cpp\n/*\n* comment pairs /* */ cannot nest.\n* ''cannot nest'' is considered source code,\n* as is the rest of the program\n*/\nint main()\n{\n    return 0;\n}\n```\n\nCompiled result(g++):\n\n![result](https://db.tt/CqQKu8GQ)\n\n## Exercise 1.8\n\n> Indicate which, if any, of the following output statements are legal:\n```cpp\nstd::cout << \"/*\";\nstd::cout << \"*/\";\nstd::cout << /* \"*/\" */;\nstd::cout << /* \"*/\" /* \"/*\" */;\n```\n> After you’ve predicted what will happen, test your answers by compiling a\nprogram with each of these statements. Correct any errors you encounter.\n\nCompiled result(g++):\n\n![result](https://db.tt/mrL9hDCS)\n\nCorrected? just added a quote:\n```cpp\nstd::cout << \"/*\";\nstd::cout << \"*/\";\nstd::cout << /* \"*/\" */\";\nstd::cout << /* \"*/\" /* \"/*\" */;\n```\n\nOutput:\n\n    /**/ */ /* \n\n## [Exercise 1.9](ex1_9.cpp)\n## [Exercise 1.10](ex1_10.cpp)\n## [Exercise 1.11](ex1_11.cpp)\n\n## Exercise 1.12\n> What does the following for loop do? What is the final value\nof sum?\n```cpp\nint sum = 0;\nfor (int i = -100; i <= 100; ++i)\n    sum += i;\n```\n\nthe loop sums the numbers from -100 to 100. the final value of sum is zero.\n\n## Exercise 1.13\n> Rewrite the exercises from § 1.4.1 (p. 13) using for loops.\n\nEx1.9:\n```cpp\n#include <iostream>\n\nint main()\n{\n    int sum = 0;\n    for (int i = 50; i <= 100; ++i) sum += i;\n    std::cout << \"the sum is: \" << sum << std::endl;\n\n    return 0;\n}\n```\n\nEx1.10:\n```cpp\n#include <iostream>\n\nint main()\n{\n    for (int i = 10; i >= 0; --i)\n        std::cout << i << std::endl;\n    return 0;\n}\n```\n\nEx1.11:\n```cpp\n#include <iostream>\n\nint main()\n{\n    std::cout << \"please input two integers:\\n\";\n    int small = 0, big = 0;\n    std::cin >> small >> big;\n\n    if (small > big)\n    {\n        int tmp = small;\n        small = big;\n        big = tmp;\n    }\n\n    for (int i = small; i != big; ++i)\n        std::cout << i << std::endl;\n\n    return 0;\n}\n```\n\n## Exercise 1.14\n> Compare and contrast the loops that used a for with those\nusing a while. Are there advantages or disadvantages to using either form?\n\n[A similar question on Stack Overflow](http://stackoverflow.com/questions/2950931/for-vs-while-in-c-programming)\n\n## Exercise 1.15\n> Write programs that contain the common errors discussed in\nthe box on page 16. Familiarize yourself with the messages the compiler\ngenerates.\n\n**Syntax Errors**:\n```c++\nint main(){\n    std::cout << \"Hello World!\" << std::endl // semicolon missed \n    return 0;\n}\n```\n\n**Type errors**:\n```c++\nint main(){\n    char s = \"Hello World!\"; // Here char should be std::string\n    std::cout << s << endl;\n    return 0;\n}\n```\n\n**Declaration errors**:\n```c++\nint main(){\n    int k = 0;\n    std::cout << K << std::endl; // use of undeclared identifier 'K'\n    return 0;\n}\n```\n\n\n## Exercise 1.16\n\n```cpp\n#include <iostream>\nint main()\n{\n    int sum = 0;\n    for (int val; std::cin >> val; sum += val);\n    std::cout << sum << std::endl;\n\n    return 0;\n}\n```\n\n## Exercise 1.17\n\n> What happens in the program presented in this section if the input values are all equal? What if there are no duplicated values?\n\nIf the input values are all equal, it will print a line which shows the count of the number you input.\n\nIf there are no duplicated values, when different values input, a new line will be printed if you click `Enter`.\n\n## Exercise 1.18\n\n> Compile and run the program from this section giving it only equal values as input. Run it again giving it values in which no number is repeated.\n\n![run](https://db.tt/F38zExnq)\n\n## Exercise 1.19\n\n> Revise the program you wrote for the exercises in § 1.4.1 (p. 13) that printed a range of numbers so that it handles input in which the first number is smaller than the second.\n\n[code](https://github.com/pezy/Cpp-Primer/blob/master/ch01/ex1_11.cpp)\n\n## Exercise 1.20\n\n> http://www.informit.com/title/032174113 contains a copy of Sales_item.h in the Chapter 1 code directory. Copy that file to your working directory. Use it to write a program that reads a set of book sales transactions, writing each transaction to the standard output.\n\n[Here](ex1_20.cpp) is the code.\n\nNote : C++11 flag need to enable.\nFor GCC and Clang, this can be done with the `-std=c++11`\n\n## Exercise 1.21\n> Write a program that reads two Sales_item objects that have the same ISBN and produces their sum.\n\nThe program should check whether the objects have the same ISBN.\n\n[Code](ex1_21.cpp)\n\n## Exercise 1.22\n\n> Write a program that reads several transactions for the same ISBN. Write the sum of all the transactions that were read.\n\nTips: this program will appear in the section 1.6.\n\n[Here](ex1_22.cpp) is the code.\n\n![run](https://db.tt/UlkuvpAS)\n\n## Exercise 1.23\n> Write a program that reads several transactions and counts\nhow many transactions occur for each ISBN.\n\nTip: please review the `1.4.4`.\n\n[Here](ex1_23.cpp) is the code.\n\n## Exercise 1.24\n> Test the previous program by giving multiple transactions\nrepresenting multiple ISBNs. The records for each ISBN should be grouped\ntogether.\n\n`data/book.txt` may be used as the records.\n\n![run](https://db.tt/EeDI7lvN)\n\n## Exercise 1.25\n> Using the Sales_item.h header from the Web site,\ncompile and execute the bookstore program presented in this section.\n\nIt is the same as Exercise 1.22.\n\n![run](https://db.tt/C6OOPuzA)\n"
  },
  {
    "path": "ch01/ex1_1.cpp",
    "content": "int main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch01/ex1_10.cpp",
    "content": "// prints the numbers from ten down to zero.(use while)\n\n#include <iostream>\n\nint main()\n{\n    int i = 10;\n    while (i >= 0)\n        std::cout << i-- << \" \";\n    return 0;\n}\n"
  },
  {
    "path": "ch01/ex1_11.cpp",
    "content": "// Print each number in the range specified by two integers.\n\n#include <iostream>\nusing std::cout;\nusing std::cin;\n\nvoid print_range(int low, int high) {\n\tif(low > high) {\n\t\tprint_range(high, low);\n\t\treturn;\n\t}\n\tfor (int i = low; i <= high; ++i) {\n\t\tcout << i << \" \";\n\t}\n}\n\nint main() {\n\tint low = 0, high = 0;\n\tcout << \"Enter two integers:\\n\";\n\tcin >> low >> high;\n\tprint_range(low, high);\n\treturn 0;\n}\n"
  },
  {
    "path": "ch01/ex1_16.cpp",
    "content": "#include <iostream>\nusing std::cin;\nusing std::cout;\nusing std::endl;\nint main()\n{\n    int sum = 0;\n    for (int i = 0; cin >> i; sum += i);\n    cout << \"Sum is: \" << sum << endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch01/ex1_20.cpp",
    "content": "#include <iostream>\n#include \"include/Sales_item.h\"\n\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    for (Sales_item item; cin >> item; cout << item << endl);\n    return 0;\n}\n"
  },
  {
    "path": "ch01/ex1_21.cpp",
    "content": "#include <iostream>\n#include \"include/Sales_item.h\"\n\nusing std::cin;\nusing std::cout;\nusing std::endl;\nusing std::cerr;\n\nint main()\n{\n    Sales_item item1, item2;\n    cin >> item1 >> item2;\n    if (item1.isbn() == item2.isbn())\n        cout << item1 + item2 << endl;\n    else\n        cerr << \"Different ISBN.\" << endl;\n}\n"
  },
  {
    "path": "ch01/ex1_22.cpp",
    "content": "#include <iostream>\n#include \"include/Sales_item.h\"\n\nint main()\n{\n    Sales_item total;\n    if (std::cin >> total)\n    {\n        Sales_item trans;\n        while (std::cin >> trans)\n        {\n            if (total.isbn() == trans.isbn())\n                total += trans;\n            else\n            {\n                std::cout << total << std::endl;\n                total = trans;\n            }\n        }\n        std::cout << total << std::endl;\n    }\n    else\n    {\n        std::cerr << \"No data?!\" << std::endl;\n        return -1;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch01/ex1_23.cpp",
    "content": "#include <iostream>\n#include \"include/Sales_item.h\"\n\nint main()\n{\n    Sales_item currItem, valItem;\n    if (std::cin >> currItem)\n    {\n        int cnt = 1;\n        while (std::cin >> valItem)\n        {\n            if (valItem.isbn() == currItem.isbn())\n            {\n                ++cnt;\n            }\n            else\n            {\n                std::cout << currItem << \" occurs \" << cnt << \" times \" << std::endl;\n                currItem = valItem;\n                cnt = 1;\n            }\n        }\n        std::cout << currItem << \" occurs \"<< cnt << \" times \" << std::endl;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "ch01/ex1_9.cpp",
    "content": "// sum the numbers from 50 to 100 (use while)\n\n#include <iostream>\n\nauto sum(int lo, int hi)\n{\n    int sum = 0;\n    while (lo <= hi) sum += lo++;\n    return sum;\n}\n\nint main()\n{\n    std::cout << \"Sum of 50 to 100 inclusive is: \" << sum(50, 100) << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch02/README.md",
    "content": "﻿### Exercise 2.1\n> What are the differences between int, long, long long,\nand short? Between an unsigned and a signed type? Between a float and\na double?\n\nC++ guarantees `short` and `int` is **at least** 16 bits, `long` **at least** 32 bits, `long long` **at least** 64 bits.\n\nThe `signed` can represent positive numbers, negative numbers and zero, while `unsigned` can only represent numbers no less than zero.\n\nThe C and C++ standards do not specify the representation of float, double and long double.\nIt is possible that all three implemented as IEEE double-precision.\nNevertheless, for most architectures (gcc, MSVC; x86, x64, ARM) float is indeed a IEEE **single-precision** floating point number (binary32),\nand double is a IEEE **double-precision** floating point number (binary64).\n\nUsage:\n\n- Use `int` for integer arithmetic. `short` is usually too small and, in practice,\n`long` often has the same size as `int`. If your data values are larger than\nthe minimum guaranteed size of an `int`, then use `long long`.\n(In a word: short < **int** < long < long long)\n\n- Use an unsigned type when you know that the values cannot be negative.\n(In a word: no negative, unsigned.)\n\n- Use double for floating-point computations; float usually does not have\nenough precision, and the cost of double-precision calculations versus\nsingle-precision is negligible. In fact, on some machines, double-precision\noperations are faster than single. The precision offered by long double\nusually is unnecessary and often entails considerable run-time cost.\n(In a word: float < **double** < long double)\n\nReference:\n\n- [What are the criteria for choosing between short / int / long data types?](https://isocpp.org/wiki/faq/newbie#choosing-int-size)\n- [Difference between float and double](http://stackoverflow.com/questions/2386772/difference-between-float-and-double)\n- Advice: Deciding which Type to Use(This book.)\n\n## Exercise 2.2\n>To calculate a mortgage payment, what types would you use\nfor the rate, principal, and payment? Explain why you selected each type.\n\nuse `double`, or also `float`.\n\nThe rate most like that: 4.50 % per year.\nThe principal most like that: $854.36\nThe payment most like that: $1, 142.36\n\nReference:\n\n- [mortgage-calculator](http://www.bankrate.com/calculators/mortgages/mortgage-calculator.aspx)\n- [What's in a Mortgage Payment?](https://thelawdictionary.org/mortgage-payment/)\n\n## Exercise 2.3\n> What output will the following code produce?\n```cpp\nunsigned u = 10, u2 = 42;\nstd::cout << u2 - u << std::endl;\nstd::cout << u - u2 << std::endl;\nint i = 10, i2 = 42;\nstd::cout << i2 - i << std::endl;\nstd::cout << i - i2 << std::endl;\nstd::cout << i - u << std::endl;\nstd::cout << u - i << std::endl;\n```\n\nOutput(g++ 4.8):\n\n```\n32\n4294967264\n32\n-32\n0\n0\n```\n\n## Exercise 2.4\n> Write a program to check whether your predictions were\ncorrect. If not, study this section until you understand what the problem is.\n\n[Here](ex2_4.cpp) is the code, please test it in your computer.\n\n## Exercise 2.5\n> Determine the type of each of the following literals. Explain\nthe differences among the literals in each of the four examples:\n- (a) 'a', L'a', \"a\", L\"a\"\n- (b) 10, 10u, 10L, 10uL, 012, 0xC\n- (c) 3.14, 3.14f, 3.14L\n- (d) 10, 10u, 10., 10e-2\n\n(a): character literal, wide character literal, string literal, string wide character literal.\n\n(b): decimal, unsigned decimal, long decimal, unsigned long decimal, octal, hexadecimal.\n\n(c): double, float, long double.\n\n(d): decimal, unsigned decimal, double, double.\n\n## Exercise 2.6\n> What, if any, are the differences between the following\ndefinitions:\n```cpp\nint month = 9, day = 7;\nint month = 09, day = 07;\n```\n\nThe first line's integer is decimal.\n\nThe second line:\n\n1. `int month = 09` is invalid, cause octal don't have digit `9`.\n2. `day` is octal.\n\n## Exercise 2.7\n> What values do these literals represent? What type does each\nhave?\n- (a) \"Who goes with F\\145rgus?\\012\"\n- (b) 3.14e1L\n- (c) 1024f\n- (d) 3.14L\n\n(a): Who goes with Fergus?(new line) \"string\"\n\n(b): 31.4 \"long double\"\n\n(c): ERROR: The suffix f is valid only with floating point literals\n\n(d): 3.14 \"long double\"\n\nReference:\n\n- [ASCII Table](http://www.asciitable.com/)\n\n## Exercise 2.8\n> Using escape sequences, write a program to print 2M followed\nby a newline. Modify the program to print 2, then a tab, then an M, followed\nby a newline.\n\n```cpp\n#include <iostream>\n\nint main()\n{\n    std::cout << 2 << \"\\115\\012\";\n    std::cout << 2 << \"\\t\\115\\012\";\n    return 0;\n}\n```\n\n## Exercise 2.9\n>Explain the following definitions. For those that are illegal,\nexplain what’s wrong and how to correct it.\n- (a) std::cin >> int input_value;\n- (b) int i = { 3.14 };\n- (c) double salary = wage = 9999.99;\n- (d) int i = 3.14;\n\n(a): error: expected '(' for function-style cast or type construction.\n```cpp\nint input_value = 0;\nstd::cin >> input_value;\n```\n\n(b):---when you compile the code without the argument \"-std=c++11\", you will get the warning below:\n    warning: implicit conversion from 'double' to 'int' changes value from 3.14 to 3.\n---when you compile the code using \"-std=c+11\", you will get a error below:\n    error: type 'double' cannot be narrowed to 'int' in initializer list\n---conclusion: Obviously, list initialization becomes strict in c++11.\n```cpp\ndouble i = { 3.14 };\n```\n\n(c): --if you declared 'wage' before, it's right. Otherwise, you'll get a error:\n    error: use of undeclared identifier 'wage'\n```cpp\ndouble wage;\ndouble salary = wage = 9999.99;\n```\n\n(d): ok: but value will be truncated.\n```cpp\ndouble i = 3.14;\n```\n\n## Exercise 2.10\n>What are the initial values, if any, of each of the following variables?\n```cpp\nstd::string global_str;\nint global_int;\nint main()\n{\n    int local_int;\n    std::string local_str;\n}\n```\n\n`global_str` is global variable, so the value is empty string.\n`global_int` is global variable, so the value is zero.\n`local_int` is a local variable which is uninitialized, so it has a undefined value.\n`local_str` is also a local variable which is uninitialized, but it has a value that is defined by the class. So it is empty string.\nPS: please read P44 in the English version, P40 in Chinese version to get more.\nThe note: Uninitialized objects of built-in type defined inside a function body have a undefined value. Objects of class type that we do not explicitly inititalize have a value that is defined by class.\n\n## Exercise 2.11\n> Explain whether each of the following is a declaration or a\ndefinition:\n- (a) extern int ix = 1024;\n- (b) int iy;\n- (c) extern int iz;\n\n    (a): definition.\n    (b): definition.\n    (c): declaration.\n\n## Exercise 2.12\n>Which, if any, of the following names are invalid?\n- (a) int double = 3.14;\n- (b) int _;\n- (c) int catch-22;\n- (d) int 1_or_2 = 1;\n- (e) double Double = 3.14;\n\n`a`, `c`, `d` are invalid.\n\n## Exercise 2.13\n>What is the value of j in the following program?\n```cpp\nint i = 42;\nint main()\n{\n    int i = 100;\n    int j = i;\n}\n```\n\n`100`, since the global `i` was hidden by the local `i`.\n\n## Exercise 2.14\n>Is the following program legal? If so, what values are printed?\n```cpp\n    int i = 100, sum = 0;\n    for (int i = 0; i != 10; ++i)\n        sum += i;\n    std::cout << i << \" \" << sum << std::endl;\n```\n\nLegal. Output:\n\n```100 45```\n\nNote: Such naming is considered as bad practise. \n\n## Exercise 2.15\n>Which of the following definitions, if any, are invalid? Why?\n- (a) int ival = 1.01;\n- (b) int &rval1 = 1.01;\n- (c) int &rval2 = ival;\n- (d) int &rval3;\n\n```\n(a): valid.\n(b): invalid. initializer must be an object.\n(c): valid.\n(d): invalid. a reference must be initialized.\n```\n\n## Exercise 2.16\n>Which, if any, of the following assignments are invalid? If they are valid, explain what they do.\n\n    int i = 0, &r1 = i; double d = 0, &r2 = d;\n- (a) r2 = 3.14159;\n- (b) r2 = r1;\n- (c) i = r2;\n- (d) r1 = d;\n\n```\n(a): valid. let d equal 3.14159.\n(b): valid. automatic convert will happen.\n(c): valid. but value will be truncated.\n(d): valid. but value will be truncated.\n```\n\n## Exercise 2.17\n>What does the following code print?\n```cpp\nint i, &ri = i;\ni = 5; ri = 10;\nstd::cout << i << \" \" << ri << std::endl;\n```\n\n`10 10`\n\n## Exercise 2.18\n>Write code to change the value of a pointer. Write code to\nchange the value to which the pointer points.\n\n```cpp\nint a = 0, b = 1;\nint *p1 = &a, *p2 = p1;\n\n// change the value of a pointer.\np1 = &b;\n// change the value to which the pointer points\n*p2 = b;\n\n```\n\n## Exercise 2.19\n>Explain the key differences between pointers and references.\n\n#### definition:\n\nthe pointer is \"points to\" any other type.\n\nthe reference is \"another name\" of an **object**.\n\n#### key difference:\n\n1. a reference is another name of an **already existing** object.\na pointer is an object in its **own right**.\n2. Once initialized, a reference remains **bound to** its initial object.\nThere is **no way** to rebind a reference to refer to a different object.\na pointer can be **assigned** and **copied**.\n3. a reference always get the object to which the reference was initially bound.\na single pointer can point to **several different objects** over its lifetime.\n4. a reference must be initialized.\na pointer need **not be** initialized at the time it is defined.\n\n## Exercise 2.20\n>What does the following program do?\n```cpp\nint i = 42;\nint *p1 = &i; *p1 = *p1 * *p1;\n```\n\n`p1` pointer to `i`, `i`'s value changed to 1764(42*42)\n\n## Exercise 2.21\n>Explain each of the following definitions. Indicate whether any are illegal and, if so, why.\n\n    int i = 0;\n\n- (a) double* dp = &i;\n- (b) int *ip = i;\n- (c) int *p = &i;\n\n```\n(a): illegal, cannot initialize a variable of type 'double *' with an\n      rvalue of type 'int *'\n(b): illegal, cannot initialize a variable of type 'int *' with an lvalue\n      of type 'int'\n(c): legal.\n```\n\n## Exercise 2.22\nAssuming p is a pointer to int, explain the following code:\n```cpp\nif (p) // ...\nif (*p) // ...\n```\n\nif (p) // whether p is nullptr?\n\nif (*p) // whether the value pointed by p is zero?\n\n## Exercise 2.23\n>Given a pointer p, can you determine whether p points to a valid object? If so, how? If not, why not?\n\nNo. Because more information needed to determine whether the pointer is valid or not.\n\n\n## Exercise 2.24\n>Why is the initialization of p legal but that of lp illegal?\n\n```cpp\nint i = 42;\nvoid *p = &i;\nlong *lp = &i;\n```\n\nInherited from C, `void*` is a special pointer that may point to any type, hence the second line is legal.\nFor type safety, C++ forbids implicit conversions like `long *lp = &i;`, thus such code is illegal.\n\n## Exercise 2.25\n>Determine the types and values of each of the following\nvariables.\n- (a) int* ip, i, &r = i;\n- (b) int i, *ip = 0;\n- (c) int* ip, ip2;\n\n```\n(a): ip is a pointer to int, i is an int, r is a reference to int i.\n(b): ip is a valid, null pointer, and i is an int.\n(c): ip is a pointer to int, and ip2 is an int.\n```\n\n## Exercise 2.26\n>Which of the following are legal? For those that are illegal,\nexplain why.\n\n```cpp\nconst int buf;      // illegal, buf is uninitialized const.\nint cnt = 0;        // legal.\nconst int sz = cnt; // legal.\n++cnt;              // legal.\n++sz;               // illegal, attempt to write to const object(sz).\n```\n\n## Exercise 2.27\n> Which of the following initializations are legal? Explain why.\n\n```cpp\nint i = -1, &r = 0;         // illegal, r must refer to an object.\nint *const p2 = &i2;        // legal.\nconst int i = -1, &r = 0;   // legal.\nconst int *const p3 = &i2;  // legal.\nconst int *p1 = &i2;        // legal\nconst int &const r2;        // illegal, r2 is a reference that cannot be const.\nconst int i2 = i, &r = i;   // legal.\n```\n\n## Exercise 2.28\n>Explain the following definitions. Identify any that are illegal.\n\n```cpp\nint i, *const cp;       // illegal, cp must initialize.\nint *p1, *const p2;     // illegal, p2 must initialize.\nconst int ic, &r = ic;  // illegal, ic must initialize.\nconst int *const p3;    // illegal, p3 must initialize.\nconst int *p;           // legal. a pointer to const int.\n```\n\n## Exercise 2.29\n>Uing the variables in the previous exercise, which of the\nfollowing assignments are legal? Explain why.\n\n```cpp\ni = ic;     // legal.\np1 = p3;    // illegal. p3 is a const pointer to const int.\np1 = &ic;   // illegal. ic is a const int.\np3 = &ic;   // illegal. p3 is a const pointer.\np2 = p1;    // illegal. p2 is a const pointer.\nic = *p3;   // illegal. ic is a const int.\n```\n\n## Exercise 2.30\n>For each of the following declarations indicate whether the\nobject being declared has top-level or low-level const.\n```cpp\nconst int v2 = 0; int v1 = v2;\nint *p1 = &v1, &r1 = v1;\nconst int *p2 = &v2, *const p3 = &i, &r2 = v2;\n```\n\nv2 is top-level const.\np2 is low-level const.\np3 is both low-level and top-level const.\nr2 is low-level const.\n\n\n## Exercise 2.31\n>Given the declarations in the previous exercise determine\nwhether the following assignments are legal. Explain how the top-level or\nlow-level const applies in each case.\n\n```cpp\nr1 = v2; // legal, top-level const in v2 is ignored.\np1 = p2; // illegal, p2 has a low-level const but p1 doesn't.\np2 = p1; // legal, we can convert int* to const int*.\np1 = p3; // illegal, p3 has a low-level const but p1 doesn't.\np2 = p3; // legal, p2 has the same low-level const qualification as p3.\n```\n\n## Exercise 2.32\n>Is the following code legal or not? If not, how might you\nmake it legal?\n\n    int null = 0, *p = null;\n\nillegal.\n```cpp\nint null = 0, *p = &null;\nint null = 0, *p = nullptr;\n```\n\n## Exercise 2.33\n>Using the variable definitions from this section, determine\nwhat happens in each of these assignments:\n```cpp\na=42; // set 42 to int a.\nb=42; // set 42 to int b.\nc=42; // set 42 to int c.\nd=42; // ERROR, d is an int *. correct: *d = 42;\ne=42; // ERROR, e is an const int *. correct: e = &c;\ng=42; // ERROR, g is a const int& that is bound to ci.\n```\n\n## Exercise 2.34\n>Write a program containing the variables and assignments from the\nprevious exercise.\nPrint the variables before and after the assignments to check\nwhether your predictions in the previous exercise were correct.\nIf not, study the examples until you can convince yourself you know\n￼￼what led you to the wrong conclusion.\n\n[Here](ex2_34.cpp) is the code.\n\n## Exercise 2.35\n>Determine the types deduced in each of the following definitions.\nOnce you’ve figured out the types,\nwrite a program to see whether you were correct.\n```cpp\nconst int i = 42;\nauto j = i; const auto &k = i; auto *p = &i; const auto j2 = i, &k2 = i;\n```\n\nj is int.\nk is const int&.\np is const int *.\nj2 is const int.\nk2 is const int&.\n\n[Here](ex2_35.cpp) is the code.\n\n## Exercise 2.36\n>In the following code, determine the type of each variable\nand the value each variable has when the code finishes:\n```cpp\nint a = 3, b = 4;\ndecltype(a) c = a;\ndecltype((b)) d = a;\n++c;\n++d;\n```\n\n`c` is an int, `d` is a reference of `a`.\nall their value are `4`.\n\n## Exercise 2.37\n>Assignment is an example of an expression that yields a reference type. The type is a reference to the type of the left-hand operand. That is, if i is an int, then the type of the expression i = x is int&. Using that knowledge, determine the type and value of each variable in this code:\n```cpp\nint a = 3, b = 4;\ndecltype(a) c = a;\ndecltype(a = b) d = a;\n```\n\n`c` is an int, `d` is a reference of int.\nthe value: a=3, b=4, c=3, d=3\n\n## Exercise 2.38\n>Describe the differences in type deduction between decltype and auto. Give an example of an expression where auto and decltype will deduce the same type and an example where they will deduce differing types.\n\nThe way `decltype` handles top-level const and references differs **subtly** from the way `auto` does.\nAnother important difference between `decltype` and `auto` is that the deduction done by decltype depends on the **form** of its given expression.\n\nso the key of difference is **subtly** and **form**.\n\n```cpp\nint i = 0, &r = i;\n// same\nauto a = i;\ndecltype(i) b = i;\n// different \"c\" will be int \"d\" will be int&\nauto c = r;\ndecltype(r) d = r;\n```\n\nMore? Look at [here](http://stackoverflow.com/questions/21369113/what-is-the-difference-between-auto-and-decltypeauto-when-returning-from-a-fun) and [here](http://stackoverflow.com/questions/12084040/decltype-vs-auto)\n\n## Exercise 2.39\n>Compile the following program to see what happens when\nyou forget the semicolon after a class definition. Remember the message for\nfuture reference.\n```cpp\nstruct Foo { /* empty  */ } // Note: no semicolon\nint main()\n{\n    return 0;\n}\n```\n\nError message: [Error] expected ';' after struct definition\n\n## Exercise 2.40\n>Write your own version of the Sales_data class.\n\n```cpp\nstruct Sale_data\n{\n    std::string bookNo;\n    std::string bookName;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n    double price = 0.0;\n    //...\n}\n```\n\n## Exercise 2.41\n>Use your Sales_data class to rewrite the exercises in §\n1.5.1(p. 22), § 1.5.2(p. 24), and § 1.6(p. 25). For now, you should define\nyour Sales_data class in the same file as your main function.\n\n####1.5.1\n\n```cpp\n#include <iostream>\n#include <string>\n\nstruct Sale_data\n{\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nint main()\n{\n    Sale_data book;\n    double price;\n    std::cin >> book.bookNo >> book.units_sold >> price;\n    book.revenue = book.units_sold * price;\n    std::cout << book.bookNo << \" \" << book.units_sold << \" \" << book.revenue << \" \" << price;\n\n    return 0;\n}\n```\n\n####1.5.2\n\n```cpp\n#include <iostream>\n#include <string>\n\nstruct Sale_data\n{\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nint main()\n{\n    Sale_data book1, book2;\n    double price1, price2;\n    std::cin >> book1.bookNo >> book1.units_sold >> price1;\n    std::cin >> book2.bookNo >> book2.units_sold >> price2;\n    book1.revenue = book1.units_sold * price1;\n    book2.revenue = book2.units_sold * price2;\n\n    if (book1.bookNo == book2.bookNo)\n    {\n        unsigned totalCnt = book1.units_sold + book2.units_sold;\n        double totalRevenue = book1.revenue + book2.revenue;\n        std::cout << book1.bookNo << \" \" << totalCnt << \" \" << totalRevenue << \" \";\n        if (totalCnt != 0)\n            std::cout << totalRevenue / totalCnt << std::endl;\n        else\n            std::cout << \"(no sales)\" << std::endl;\n        return 0;\n    }\n    else\n    {\n        std::cerr << \"Data must refer to same ISBN\" << std::endl;\n        return -1;  // indicate failure\n    }\n}\n```\n\n####1.6\n\n```cpp\n#include <iostream>\n#include <string>\n\nstruct Sale_data\n{\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nint main()\n{\n    Sale_data total;\n    double totalPrice;\n    if (std::cin >> total.bookNo >> total.units_sold >> totalPrice)\n    {\n        total.revenue = total.units_sold * totalPrice;\n\n        Sale_data trans;\n        double transPrice;\n        while (std::cin >> trans.bookNo >> trans.units_sold >> transPrice)\n        {\n            trans.revenue = trans.units_sold * transPrice;\n\n            if (total.bookNo == trans.bookNo)\n            {\n                total.units_sold += trans.units_sold;\n                total.revenue += trans.revenue;\n            }\n            else\n            {\n                std::cout << total.bookNo << \" \" << total.units_sold << \" \" << total.revenue << \" \";\n                if (total.units_sold != 0)\n                    std::cout << total.revenue / total.units_sold << std::endl;\n                else\n                    std::cout << \"(no sales)\" << std::endl;\n\n                total.bookNo = trans.bookNo;\n                total.units_sold = trans.units_sold;\n                total.revenue = trans.revenue;\n            }\n        }\n\n        std::cout << total.bookNo << \" \" << total.units_sold << \" \" << total.revenue << \" \";\n        if (total.units_sold != 0)\n            std::cout << total.revenue / total.units_sold << std::endl;\n        else\n            std::cout << \"(no sales)\" << std::endl;\n\n        return 0;\n    }\n    else\n    {\n        std::cerr << \"No data?!\" << std::endl;\n        return -1;  // indicate failure\n    }\n}\n```\n\n## Exercise 2.42\n>Write your own version of the Sales_data.h header and use it to rewrite the exercise from § 2.6.2(p. 76)\n\n\n- 1.5.1. [Code](ex2_42_1.cpp)\n- 1.5.2. [Code](ex2_42_2.cpp)\n- 1.6. [Code](ex2_42_3.cpp)\n"
  },
  {
    "path": "ch02/ex2_34.cpp",
    "content": "#include <iostream>\n\nint main()\n{\n    int i = 0, &r = i;\n    auto a = r;   // a is an int (r is an alias for i, which has type int)\n\n    const int ci = i, &cr = ci;\n    auto b = ci; // b is an int (top-level const in ci is dropped)\n    auto c = cr; // c is an int (cr is an alias for ci whose const is top-level)\n    auto d = &i; // d is an int* (& ofan int objectis int*)\n    auto e = &ci; // e is const int*(& of a const object is low-level const)\n\n    const auto f = ci; // deduced type of ci is int; f has type const int\n    auto &g = ci; // g is a const int& that is bound to ci\n\n    a = 42; b = 42; c = 42; *d = 42; e = &c;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch02/ex2_35.cpp",
    "content": "#include <iostream>\n#include <typeinfo>\n\nint main()\n{\n    const int i = 42;\n    auto j = i;\n    const auto &k = i;\n    auto *p = &i;\n    const auto j2 = i, &k2 = i;\n\n    // print i means int, and PKi means pointer to const int.\n    std::cout   << \"j is \"      << typeid(j).name()\n                << \"\\nk is \"    << typeid(k).name()\n                << \"\\np is \"    << typeid(p).name()\n                << \"\\nj2 is \"   << typeid(j2).name()\n                << \"\\nk2 is \"   << typeid(k2).name()\n                << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch02/ex2_4.cpp",
    "content": "#include <iostream>\n\nint main()\n{\n    unsigned u = 10, u2 = 42;\n    std::cout << u2 - u << std::endl;   // 32\n    std::cout << u - u2 << std::endl;   // 4294967264\n    int i = 10, i2 = 42;\n    std::cout << i2 - i << std::endl;   // 32\n    std::cout << i - i2 << std::endl;   // -32\n    std::cout << i - u << std::endl;    // 0\n    std::cout << u - i << std::endl;    // 0\n\n    return 0;\n}\n"
  },
  {
    "path": "ch02/ex2_42.h",
    "content": "#ifndef CH02_EX2_42_H_\n#define CH02_EX2_42_H_\n\n#include <string>\n#include <iostream>\n\nstruct Sales_data\n{\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n\n    void CalcRevenue(double price);\n    double CalcAveragePrice();\n    void SetData(Sales_data data);\n    void AddData(Sales_data data);\n    void Print();\n};\n\nvoid Sales_data::CalcRevenue(double price)\n{\n    revenue = units_sold * price;\n}\n\nvoid Sales_data::SetData(Sales_data data)\n{\n    bookNo = data.bookNo;\n    units_sold = data.units_sold;\n    revenue = data.revenue;\n}\n\nvoid Sales_data::AddData(Sales_data data)\n{\n    if (bookNo != data.bookNo) return;\n    units_sold += data.units_sold;\n    revenue += data.revenue;\n}\n\ndouble Sales_data::CalcAveragePrice()\n{\n    if (units_sold != 0)\n        return revenue / units_sold;\n    else\n        return 0.0;\n}\n\nvoid Sales_data::Print()\n{\n    std::cout << bookNo << \" \" << units_sold << \" \" << revenue << \" \";\n    double averagePrice = CalcAveragePrice();\n    if (averagePrice != 0.0)\n        std::cout << averagePrice << std::endl;\n    else\n        std::cout << \"(no sales)\" << std::endl;\n}\n\n#endif // CH02_EX2_42_H_\n"
  },
  {
    "path": "ch02/ex2_42_1.cpp",
    "content": "#include <iostream>\n#include \"ex2_42.h\"\n\nint main()\n{\n    Sales_data book;\n    double price;\n    std::cin >> book.bookNo >> book.units_sold >> price;\n    book.CalcRevenue(price);\n    book.Print();\n\n    return 0;\n}\n"
  },
  {
    "path": "ch02/ex2_42_2.cpp",
    "content": "#include <iostream>\n#include \"ex2_42.h\"\n\nint main()\n{\n    Sales_data book1, book2;\n    double price1, price2;\n    std::cin >> book1.bookNo >> book1.units_sold >> price1;\n    std::cin >> book2.bookNo >> book2.units_sold >> price2;\n    book1.CalcRevenue(price1);\n    book2.CalcRevenue(price2);\n\n    if (book1.bookNo == book2.bookNo)\n    {\n        book1.AddData(book2);\n        book1.Print();\n        return 0;\n    }\n    else\n    {\n        std::cerr << \"Data must refer to same ISBN\" << std::endl;\n        return -1;  // indicate failure\n    }\n}\n"
  },
  {
    "path": "ch02/ex2_42_3.cpp",
    "content": "#include <iostream>\n#include \"ex2_42.h\"\n\nint main()\n{\n    Sales_data total;\n    double totalPrice;\n    if (std::cin >> total.bookNo >> total.units_sold >> totalPrice)\n    {\n        total.CalcRevenue(totalPrice);\n        Sales_data trans;\n        double transPrice;\n        while (std::cin >> trans.bookNo >> trans.units_sold >> transPrice)\n        {\n            trans.CalcRevenue(transPrice);\n            if (total.bookNo == trans.bookNo)\n            {\n                total.AddData(trans);\n            }\n            else\n            {\n                total.Print();\n                total.SetData(trans);\n            }\n        }\n        total.Print();\n        return 0;\n    }\n    else\n    {\n        std::cerr << \"No data?!\" << std::endl;\n        return -1;  // indicate failure\n    }\n}\n"
  },
  {
    "path": "ch03/README.md",
    "content": "## Exercise 3.1 : [part1](ex3_1a.cpp) | [part2](ex3_1b.cpp)\n## Exercise 3.2 : [part1](ex3_2a.cpp) | [part2](ex3_2b.cpp)\n## Exercise 3.3\n>Explain how whitespace characters are handled in the string\ninput operator and in the `getline` function.\n\n * For code like `is >> s`, input is separated by whitespaces while reading into string `s`.\n * For code like `getline(is, s)` input is separated by newline `\\n` while reading into string `s`. Other whitespaces are ignored.\n * For code like `getline(is, s, delim)`input is separated by `delim` while reading into string `s`. All whitespaces are ignored.\n\n## Exercise 3.4 : [part1](ex3_4a.cpp) | [part2](ex3_4b.cpp)\n## Exercise 3.5 : [part1](ex3_5a.cpp) | [part2](ex3_5b.cpp)\n\n## [Exercise 3.6](ex3_6.cpp)\n## Exercise 3.7\n>What would happen if you define the loop control variable in the previous\nexercise as type char? Predict the results and then change your program\nto use a char to see if you were right.\n\nThe point here is using reference to mutate a string. If changed to something like below, `c` would become a `char` rather than `char&`. In such case, `c` is a copy of each character of string `str`, thus the assignment `c = 'X'` won't mutate `str`. As a result, after this for range statement, nothing changes. \n```cpp\nstring str(\"a simple string\");\nfor (char c : str) c = 'X';\n```\n\n## [Exercise 3.8](ex3_8.cpp)\n## Exercise 3.9\n>What does the following program do? Is it valid? If not, why not?\n```cpp\nstring s;\ncout << s[0] << endl;\n```\n\nThis code was dereferencing and printing the first item stored in `s`. Since `s` is empty, such operation is invalid, a.k.a. **undefined behavior**. \n\n\n## [Exercise 3.10](ex3_10.cpp)\n## Exercise 3.11\n>Is the following range for legal? If so, what is the type of c?\n```cpp\nconst string s = \"Keep out!\";\nfor (auto &c : s){ /*... */ }\n```\n\nDepending on the code within for loop body. For example:\n\n    cout << c;  // legal.\n    c = 'X';    // illegal.\n\nThe type of `c` is `const char&`. \n\n## Exercise 3.12\n>Which, if any, of the following vector definitions are in error?\nFor those that are legal, explain what the definition does.\nFor those that are not legal, explain why they are illegal.\n```cpp\nvector<vector<int>> ivec;         // legal(c++11), vectors.\nvector<string> svec = ivec;       // illegal, different type.\nvector<string> svec(10, \"null\");  // legal, vector have 10 strings: \"null\".\n```\n\n## Exercise 3.13\n>How many elements are there in each of the following\nvectors? What are the values of the elements?\n```cpp\nvector<int> v1;         // size:0,  no values.\nvector<int> v2(10);     // size:10, value:0\nvector<int> v3(10, 42); // size:10, value:42\nvector<int> v4{ 10 };     // size:1,  value:10\nvector<int> v5{ 10, 42 }; // size:2,  value:10, 42\nvector<string> v6{ 10 };  // size:10, value:\"\"\nvector<string> v7{ 10, \"hi\" };  // size:10, value:\"hi\"\n```\n\n## [Exercise 3.14](ex3_14.cpp)\n## [Exercise 3.15](ex3_15.cpp)\n## [Exercise 3.16](ex3_16.cpp)\n## [Exercise 3.17](ex3_17.cpp)\n## [Exercise 3.18](ex3_18.cpp)\n## [Exercise 3.19](ex3_19.cpp)\n## Exercise 3.20 : [part1](ex3_20a.cpp) | [part2](ex3_20b.cpp)\n## [Exercise 3.21](ex3_21.cpp)\n## [Exercise 3.22](ex3_22.cpp)\n## [Exercise 3.23](ex3_23.cpp)\n## [Exercise 3.24](ex3_24.cpp)\n## [Exercise 3.25](ex3_25.cpp)\n## Exercise 3.26\n>In the binary search program on page 112,\nwhy did we write `mid=beg+(end-beg)/2;` instead of `mid=(beg+end) /2;`?\n\nThere's no operator `+` for adding two iterators.\n\n## Exercise 3.27\n>Assuming txt_size is a function that takes no arguments\nand returns an int value, which of the following definitions are illegal?\nExplain why.\n\n```cpp\nunsigned buf_size = 1024;\n\nint ia[buf_size];   // illegal, The dimension value must be a constant expression.\nint ia[4 * 7 - 14]; // legal\nint ia[txt_size()]; // illegal, The dimension value must be a constant expression.\nchar st[11] = \"fundamental\";  // illegal, the string's size is 12.\n```\n\n## Exercise 3.28\n>What are the values in the following arrays?\n\n```cpp\nstring sa[10];      //all elements are empty strings\nint ia[10];         //all elements are 0\n\nint main() \n{\n    string sa2[10]; //all elements are empty strings\n    int ia2[10];    //all elements are undefined\n}\n```\n\n## Exercise 3.29:\n>List some of the drawbacks of using an array instead of a vector.\n\n1. Size is fixed at compiling time.\n2. No API as that of vector.\n3. Bug prone.\n\n## Exercise 3.30\n>Identify the indexing errors in the following code:\n```cpp\nconstexpr size_t array_size = 10;\nint ia[array_size];\nfor (size_t ix = 1; ix <= array_size; ++ix)\n      ia[ix] = ix;\n```\n\nWhen `ix` equal to 10, the expression `ia[ix]` becomes a **UB**, as it is trying to dereference an element out of range.\n\n## [Exercise 3.31](ex3_31.cpp)\n## [Exercise 3.32](ex3_32.cpp)\n## Exercise 3.33\n>What would happen if we did not initialize the scores array in the program\non page 116?\n\nIf so, values of array are undefined. Like this:\n\n![result](https://db.tt/3T4TQoo8)\n\n## Exercise 3.34\n>Given that p1 and p2 point to elements in the same array, what does the following code do?\nAre there values of p1 or p2 that make this code illegal?\n\n```cpp\np1 += p2 - p1;\n```\n * It moves `p1` with the offset `p2 - p1`. After this statement, `p1` and `p2` points to the same address. \n * Any legal value p1, p2 make this code legal.\n\n## [Exercise 3.35](ex3_35.cpp)\n## [Exercise 3.36](ex3_36.cpp)\n## Exercise 3.37\n>What does the following program do?\n```cpp\nconst char ca[] = { 'h', 'e', 'l', 'l', 'o' };\nconst char *cp = ca;\nwhile (*cp) {\n    cout << *cp << endl;\n    ++cp;\n}\n```\n\nThis code will print all characters in `ca`, afterwards as no `\\0` appended, **UB** would happen. For most cases, the while loop here won't be terminated as expected and many rubbish would be printed out. \n\n\n## Exercise 3.38\n>In this section, we noted that it was not only illegal but meaningless to try to add two pointers.\nWhy would adding two pointers be meaningless?\n\nSee:\n- [Why can't I add pointers](http://stackoverflow.com/questions/2935038/why-cant-i-add-pointers)\n\n## [Exercise 3.39](ex3_39.cpp)\n## [Exercise 3.40](ex3_40.cpp)\n## [Exercise 3.41](ex3_41.cpp)\n## [Exercise 3.42](ex3_42.cpp)\n## [Exercise 3.43](ex3_43.cpp)\n## [Exercise 3.44](ex3_44.cpp)\n## [Exercise 3.45](ex3_45.cpp)\n"
  },
  {
    "path": "ch03/ex3_10.cpp",
    "content": "//reads a string of characters including punctuation and writes what was read but with the punctuation removed.\n\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cout;\nusing std::cin;\nusing std::endl;\n\nint main()\n{\n    cout << \"Enter a string of characters including punctuation.\" << endl;\n    for (string s; getline(cin, s); cout << endl)\n        for (auto i : s) \n            if (!ispunct(i)) cout << i;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_14.cpp",
    "content": "//\n//@Author  @PEZY @Yue Wang \n//@Date    Aug. 2014 Jun.2015\n//@Brief\n// read a sequence of ints from cin and\n// store those values in a vector.\n//\n\n#include <iostream>\n#include <vector>\n\nint main()\n{\n    std::vector<int> vec;\n    for (int i; std::cin >> i; vec.push_back(i));\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_15.cpp",
    "content": "//\n//@Author  @PEZY @Yue Wang \n//@Date    Aug. 2014, Jun 2015\n//@Brief\n// read a sequence of strings from cin and\n// store those values in a vector.\n//\n\n#include <iostream>\n#include <vector>\n#include <string>\n\nint main()\n{\n    std::vector<std::string> vec;\n    for (std::string buffer; std::cin >> buffer; vec.push_back(buffer));\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_16.cpp",
    "content": "//\n//@Author  PEZY\n//@Date    Aug. 2014\n//@Brief \n// print the size and contents of the vectors from exercise 3.13.\n// Check whether your answers to that exercise were correct. \n// If not, restudy § 3.3.1 (p. 97) until you understand why you were wrong.\n//\n\n#include <iostream>\n#include <vector>\n#include <string>\n\nusing std::vector;\nusing std::string;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    vector<int> v1;\n    cout << \"{\\n \\\"v1\\\":{\\\"size\\\":\\\"\" << v1.size() << \"\\\",\\\"value\\\":[\";\n    for (auto i : v1)\n        cout << i << \",\";\n    if (!v1.empty()) cout << \"\\b\";\n    cout << \"]}\" << endl;\n\n    vector<int> v2(10);\n    cout << \" \\\"v2\\\":{\\\"size\\\":\\\"\" << v2.size() << \"\\\",\\\"value\\\":[\";\n    for (auto i : v2)\n        cout << i << \",\";\n    if (!v2.empty()) cout << \"\\b\";\n    cout << \"]}\" << endl;\n\n    vector<int> v3(10, 42);\n    cout << \" \\\"v3\\\":{\\\"size\\\":\\\"\" << v3.size() << \"\\\",\\\"value\\\":[\";\n    for (auto i : v3)\n        cout << i << \",\";\n    if (!v3.empty()) cout << \"\\b\";\n    cout << \"]}\" << endl;\n\n    vector<int> v4{ 10 };\n    cout << \" \\\"v4\\\":{\\\"size\\\":\\\"\" << v4.size() << \"\\\",\\\"value\\\":[\";\n    for (auto i : v4)\n        cout << i << \",\";\n    if (!v4.empty()) cout << \"\\b\";\n    cout << \"]}\" << endl;\n\n    vector<int> v5{ 10, 42 };\n    cout << \" \\\"v5\\\":{\\\"size\\\":\\\"\" << v5.size() << \"\\\",\\\"value\\\":[\";\n    for (auto i : v5)\n        cout << i << \",\";\n    if (!v5.empty()) cout << \"\\b\";\n    cout << \"]}\" << endl;\n\n    vector<string> v6{ 10 };\n    cout << \" \\\"v6\\\":{\\\"size\\\":\\\"\" << v6.size() << \"\\\",\\\"value\\\":[\";\n    for (auto i : v6)\n        if (i.empty()) cout << \"(null)\" << \",\";\n        else cout << i << \",\";\n        if (!v6.empty()) cout << \"\\b\";\n        cout << \"]}\" << endl;\n\n        vector<string> v7{ 10, \"hi\" };\n        cout << \" \\\"v7\\\":{\\\"size\\\":\\\"\" << v7.size() << \"\\\",\\\"value\\\":[\";\n        for (auto i : v7)\n            if (i.empty()) cout << \"(null)\" << \",\";\n            else cout << i << \",\";\n            if (!v7.empty()) cout << \"\\b\";\n            cout << \"]}\\n}\" << endl;\n\n            return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_17.cpp",
    "content": "//\n//@Author  @PEZY @Yue Wang \n//@Date    Aug. 2014 Jun.2015\n//@Brief\n// Read a sequence of words from cin and store the values a vector.\n// After you've read all the words, process the vector and change each word to uppercase.\n// Print the transformed elements, eight words to a line.\n//\n\n#include <iostream>\n#include <vector>\n#include <string>\n\nusing std::cin;\nusing std::cout;\nusing std::endl;\nusing std::vector;\nusing std::string;\n\nint main()\n{\n    vector<string> vec;\n    for (string word; cin >> word; vec.push_back(word));\n    for (auto &str : vec) for (auto &c : str) c = toupper(c);\n\n    for (string::size_type i = 0; i != vec.size(); ++i)\n    {\n        if (i != 0 && i % 8 == 0) cout << endl;\n        cout << vec[i] << \" \";\n    }\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_18.cpp",
    "content": "#include <vector>\n\nint main()\n{\n    std::vector<int> ivec{ 42 };\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_19.cpp",
    "content": "//\n//@Author  @PEZY       @Yue Wang   \n//@Date    Aug. 2014   Jun. 2015\n//@Brief\n// List three ways to define a vector and give it ten elements,\n// each with the value 42.\n// Indicate whether there is a preferred way to do so and why.\n\n#include <iostream>\n#include <vector>\nusing std::vector;\n\nint main()\n{\n    vector<int> ivec1(10, 42);\n    vector<int> ivec2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };\n    vector<int> ivec3;\n    for (int i = 0; i != 10; ++i) ivec3.push_back(42);\n    std::cout << \"The first approach is better!\" << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_1a.cpp",
    "content": "// use `using` for 1.4.1\n\n#include <iostream>\n\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    int sum = 0;\n    for (int val = 1; val <= 10; ++val) sum += val;\n    cout << \"Sum of 1 to 10 inclusive is \" << sum << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_1b.cpp",
    "content": "#include <iostream>\n#include <string>\n#include \"../ch02/ex2_42.h\"\n\nusing std::cin;\nusing std::cout;\nusing std::endl;\nusing std::cerr;\n\nint main()\n{\n    Sales_data data1, data2;\n\n    // code to read into data1 and data2\n    double price = 0;  // price per book, used to calculate total revenue\n\n    // read the first transactions: ISBN, number of books sold, price per book \n    cin >> data1.bookNo >> data1.units_sold >> price;\n    // calculate total revenue from price and units_sold\n    data1.revenue = data1.units_sold * price;\n\n    // read the second transaction\n    cin >> data2.bookNo >> data2.units_sold >> price;\n    data2.revenue = data2.units_sold * price;\n\n    // code to check whether data1 and data2 have the same ISBN\n    //        and if so print the sum of data1 and data2\n    if (data1.bookNo == data2.bookNo)\n    {\n        unsigned totalCnt = data1.units_sold + data2.units_sold;\n        double totalRevenue = data1.revenue + data2.revenue;\n\n        // print: ISBN, total sold, total revenue, average price per book\n        cout << data1.bookNo << \" \" << totalCnt\n            << \" \" << totalRevenue << \" \";\n        if (totalCnt != 0)\n            cout << totalRevenue / totalCnt << endl;\n        else\n            cout << \"(no sales)\" << endl;\n\n        return 0;  // indicate success\n    }\n    else\n    {  // transactions weren't for the same ISBN\n        cerr << \"Data must refer to the same ISBN\" << endl;\n        return -1; // indicate failure\n    }\n}\n"
  },
  {
    "path": "ch03/ex3_20a.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nusing std::vector; using std::cout; using std::endl; using std::cin;\n\nint main()\n{\n    vector<int> ivec;\n    for (int i; cin >> i; ivec.push_back(i));\n\n    if (ivec.empty())\n    {\n        cout << \"input at least one integer.\" << endl;\n        return -1;\n    }\n\n    if (ivec.size() == 1)\n    {\n        cout << \"only one integer \" << ivec[0] << \", it doesn't have any adjacent elements.\" << endl;\n        return -1;\n    }\n\n    for (int i = 0; i < ivec.size() - 1; ++i)\n        cout << ivec[i] + ivec[i + 1] << \" \";\n    cout << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_20b.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nusing std::vector;\nusing std::cout;\nusing std::endl;\nusing std::cin;\n\nint main()\n{\n    vector<int> ivec;\n    for (int i; cin >> i; ivec.push_back(i));\n\n    if (ivec.empty())\n    {\n        cout << \"input at least one integer.\" << endl;\n        return -1;\n    }\n\n    // If the vector has odd size, element in the middle will add to itself.\n    auto size = (ivec.size() + 1) / 2;\n\n    for (int i = 0; i != size; ++i)\n        cout << ivec[i] + ivec[ivec.size() - i - 1] << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_21.cpp",
    "content": "//\n//Redo the first exercise from § 3.3.3 (p. 105) using iterators.\n//\n\n#include <vector>\n#include <iterator>\n#include <string>\n#include <iostream>\n\nusing std::vector;\nusing std::string;\nusing std::cout;\nusing std::endl;\n\nvoid check_and_print(const vector<int>& vec)\n{\n    cout << \"size: \" << vec.size() << \"  content: [\";\n    for (auto it = vec.begin(); it != vec.end(); ++it)\n        cout << *it << (it != vec.end() - 1 ? \",\" : \"\");\n    cout << \"]\\n\" << endl;\n}\n\nvoid check_and_print(const vector<string>& vec)\n{\n\n    cout << \"size: \" << vec.size() << \"  content: [\";\n    for (auto it = vec.begin(); it != vec.end(); ++it)\n        cout << *it << (it != vec.end() - 1 ? \",\" : \"\");\n    cout << \"]\\n\" << endl;\n}\n\nint main()\n{\n    vector<int> v1;\n    vector<int> v2(10);\n    vector<int> v3(10, 42);\n    vector<int> v4{ 10 };\n    vector<int> v5{ 10, 42 };\n    vector<string> v6{ 10 };\n    vector<string> v7{ 10, \"hi\" };\n\n    check_and_print(v1);\n    check_and_print(v2);\n    check_and_print(v3);\n    check_and_print(v4);\n    check_and_print(v5);\n    check_and_print(v6);\n    check_and_print(v7);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_22.cpp",
    "content": "//\n//Revise the loop that printed the first paragraph in text \n//to instead change the elements in text that correspond \n//to the first paragraph to all uppercase. \n//After you’ve updated text, print its contents.\n//\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cctype>\n\nusing std::vector; using std::string; using std::cout; using std::cin; using std::isalpha;\n\nint main()\n{\n    vector<string> text;\n    for (string line; getline(cin, line); text.push_back(line));\n    \n    for (auto& word : text)\n    {\n        for (auto& ch : word)\n            if (isalpha(ch)) ch = toupper(ch);\n        cout << word << \" \";\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_23.cpp",
    "content": "//\n//Write a program to create a vector with ten int elements. \n//Using an iterator, assign each element a value that is twice its current value.\n// Test your program by printing the vector.\n//\n\n#include <vector>\n#include <iostream>\n#include <iterator>\n\nusing std::vector; using std::iterator; using std::cout;\n\nint main()\n{\n    vector<int> v{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    for (auto it = v.begin(); it != v.end(); ++it) *it *= 2;\n    for (auto i : v) cout << i << \" \";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_24.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nusing std::vector; using std::cout; using std::endl; using std::cin;\n\nint main()\n{\n    vector<int> v;\n    for (int buffer; cin >> buffer; v.push_back(buffer));\n\n    if (v.size() < 2)\n    {\n        cout << \" please enter at least two integers\";\n        return -1;\n    }\n\n    for (auto it = v.cbegin(); it + 1 != v.cend(); ++it)\n        cout << *it + *(it + 1) << \" \";\n    cout << endl;\n\n    for (auto lft = v.cbegin(), rht = v.cend() - 1; lft <= rht; ++lft, --rht)\n        cout << *lft + *rht << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_25.cpp",
    "content": "#include <vector>\n#include <iostream>\n\nusing std::vector; using std::cout; using std::cin; using std::endl;\n\nint main()\n{\n    vector<unsigned> scores(11, 0);\n    for (unsigned grade; cin >> grade;/* */)\n        if (grade <= 100)\n            ++*(scores.begin() + grade / 10);\n\n    for (auto s : scores) \n        cout << s << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_2a.cpp",
    "content": "// read the standard input a line at a time.\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::endl;\nusing std::getline;\n\nint main()\n{\n    for (string str; getline(cin, str); cout << str << endl);\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_2b.cpp",
    "content": "// read the standard input a word at a time\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    for (string str; cin >> str; cout << str << endl);\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_31.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::endl;\n\nint main()\n{\n    int arr[10];\n    for (auto i = 0; i < 10; ++i) arr[i] = i;\n    for (auto i : arr) cout << i << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_32.cpp",
    "content": "#include <iostream>\n#include <vector>\nusing std::cout; using std::endl; using std::vector;\n\nint main()\n{\n    // array\n    int arr[10];\n    for (int i = 0; i < 10; ++i) arr[i] = i;\n    int arr2[10];\n    for (int i = 0; i < 10; ++i) arr2[i] = arr[i];\n\n    // vector\n    vector<int> v(10);\n    for (int i = 0; i != 10; ++i) v[i] = arr[i];\n    vector<int> v2(v);\n    for (auto i : v2) cout << i << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_35.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::endl;\n\nint main()\n{\n    const int size = 10;\n    int arr[size];\n    for (auto ptr = arr; ptr != arr + size; ++ptr) *ptr = 0;\n\n    for (auto i : arr) cout << i << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_36.cpp",
    "content": "#include <iostream>\n#include <vector>\n#include <iterator>\n\nusing std::begin; using std::end; using std::cout; using std::endl; using std::vector;\n\n// pb point to begin of the array, pe point to end of the array.\nbool compare(int* const pb1, int* const pe1, int* const pb2, int* const pe2)\n{\n    if ((pe1 - pb1) != (pe2 - pb2)) // have different size.\n        return false;\n    else\n    {\n        for (int* i = pb1, *j = pb2; (i != pe1) && (j != pe2); ++i, ++j)\n            if (*i != *j) return false;\n    }\n\n    return true;\n}\n\nint main()\n{\n    int arr1[3] = { 0, 1, 2 };\n    int arr2[3] = { 0, 2, 4 };\n\n    if (compare(begin(arr1), end(arr1), begin(arr2), end(arr2)))\n        cout << \"The two arrays are equal.\" << endl;\n    else\n        cout << \"The two arrays are not equal.\" << endl;\n\n    cout << \"==========\" << endl;\n\n    vector<int> vec1 = { 0, 1, 2 };\n    vector<int> vec2 = { 0, 1, 2 };\n\n    if (vec1 == vec2)\n        cout << \"The two vectors are equal.\" << endl;\n    else\n        cout << \"The two vectors are not equal.\" << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_39.cpp",
    "content": "#include <iostream>\n#include <string>\n#include <cstring>\nusing std::cout; using std::endl; using std::string;\n\nint main()\n{\n    // use string.\n    string s1(\"Mooophy\"), s2(\"Pezy\");\n    if (s1 == s2)\n        cout << \"same string.\" << endl;\n    else if (s1 > s2)\n        cout << \"Mooophy > Pezy\" << endl;\n    else\n        cout << \"Mooophy < Pezy\" << endl;\n\n    cout << \"=========\" << endl;\n\n    // use C-Style character strings.\n    const char* cs1 = \"Wangyue\";\n    const char* cs2 = \"Pezy\";\n    auto result = strcmp(cs1, cs2);\n    if (result == 0)\n        cout << \"same string.\" << endl;\n    else if (result < 0)\n        cout << \"Wangyue < Pezy\" << endl;\n    else\n        cout << \"Wangyue > Pezy\" << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_40.cpp",
    "content": "// more discuss: https://github.com/Mooophy/Cpp-Primer/pull/241\n// @frank67\n\n#include <iostream>\n#include <cstring>\n\nconst char cstr1[]=\"Hello\";\nconst char cstr2[]=\"world!\";\n\nint main()\n{\n    constexpr size_t new_size = strlen(cstr1) + strlen(\" \") + strlen(cstr2) +1;\n    char cstr3[new_size];\n    \n    strcpy(cstr3, cstr1);\n    strcat(cstr3, \" \");\n    strcat(cstr3, cstr2);\n    \n    std::cout << cstr3 << std::endl;\n}\n"
  },
  {
    "path": "ch03/ex3_41.cpp",
    "content": "#include <iostream>\n#include <vector>\nusing std::vector; using std::cout; using std::endl; using std::begin; using std::end;\n\nint main()\n{\n    int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    vector<int> v(begin(arr), end(arr));\n\n    for (auto i : v) cout << i << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_42.cpp",
    "content": "#include <iostream>\n#include <vector>\nusing std::vector; using std::cout; using std::endl; using std::begin; using std::end;\n\nint main()\n{\n    vector<int> v{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    int arr[10];\n    for (int i = 0; i != v.size(); ++i) arr[i] = v[i];\n\n    for (auto i : arr) cout << i << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_43.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::endl;\n\nint main()\n{\n    int arr[3][4] = \n    { \n        { 0, 1, 2, 3 },\n        { 4, 5, 6, 7 },\n        { 8, 9, 10, 11 }\n    };\n\n    // range for\n    for (const int(&row)[4] : arr)\n        for (int col : row) cout << col << \" \";\n    cout << endl;\n\n    // for loop\n    for (size_t i = 0; i != 3; ++i)\n        for (size_t j = 0; j != 4; ++j) cout << arr[i][j] << \" \";\n    cout << endl;\n\n    // using pointers.\n    for (int(*row)[4] = arr; row != arr + 3; ++row)\n        for (int *col = *row; col != *row + 4; ++col) cout << *col << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_44.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::endl;\n\nint main()\n{\n    int ia[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };\n\n    // a range for to manage the iteration\n    // use type alias\n    using int_array = int[4];\n    for (int_array& p : ia)\n        for (int q : p)\n            cout << q << \" \";\n    cout << endl;\n\n    // ordinary for loop using subscripts\n    for (size_t i = 0; i != 3; ++i)\n        for (size_t j = 0; j != 4; ++j)\n            cout << ia[i][j] << \" \";\n    cout << endl;\n\n    // using pointers.\n    // use type alias\n    for (int_array* p = ia; p != ia + 3; ++p)\n        for (int *q = *p; q != *p + 4; ++q)\n            cout << *q << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_45.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::endl;\n\nint main()\n{\n    int ia[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };\n\n    // a range for to manage the iteration\n    for (auto& p : ia)\n        for (int q : p)\n            cout << q << \" \";\n    cout << endl;\n\n    // ordinary for loop using subscripts\n    for (size_t i = 0; i != 3; ++i)\n        for (size_t j = 0; j != 4; ++j)\n            cout << ia[i][j] << \" \";\n    cout << endl;\n\n    // using pointers.\n    for (auto p = ia; p != ia + 3; ++p)\n        for (int *q = *p; q != *p + 4; ++q)\n            cout << *q << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_4a.cpp",
    "content": "// read two strings and report whether the strings are equal\n// If not, report which of the two is larger.\n#include <iostream>\n#include <string>\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    string str1, str2;\n    while (cin >> str1 >> str2)\n    {\n        if (str1 == str2)\n            cout << \"The two strings are equal.\" << endl;\n        else\n            cout << \"The larger string is \" << ((str1 > str2) ? str1 : str2);\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_4b.cpp",
    "content": "// read two strings and report whether the strings have the same length\n// If not, report which is longer\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    for (string str1, str2; cin >> str1 >> str2;/* */)\n    {\n        if (str1.size() == str2.size())\n            cout << \"The two strings have the same length.\" << endl;\n        else\n            cout << \"The longer string is \" << ((str1.size() > str2.size()) ? str1 : str2) << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_5a.cpp",
    "content": "//read strings from the standard input, concatenating what is read into one large string. \n//Print the concatenated string.\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    string concatenated;\n    for (string buffer; cin >> buffer; concatenated += buffer);\n    cout << \"The concatenated string is \" << concatenated << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_5b.cpp",
    "content": "//separate adjacent input strings by a space.\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    string str;\n    for (string buff; cin >> buff; str += (str.empty() ? \"\" : \" \") + buff);\n    cout << \"The concatenated string is \" << str << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_6.cpp",
    "content": "//Use a range for to change all the characters in a string to X.\n\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    string str(\"a simple string\");\n    for (auto &c : str) c = 'X';\n    cout << str << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch03/ex3_8.cpp",
    "content": "#include <iostream>\n#include <string>\nusing std::string;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    string str(\"a simple string\");\n    \n    // while\n    decltype(str.size()) i = 0;\n    while (i < str.size()) str[i++] = 'X';\n    cout << str << endl;\n\n    // for\n    for (i = 0; i < str.size(); str[i++] = 'Y');\n    cout << str << endl;\n\n    // I like range for.\n    return 0;\n}\n"
  },
  {
    "path": "ch04/README.md",
    "content": "## Exercise 4.1\n>What is the value returned by 5 + 10 * 20/2?\n\n105\n\n## Exercise 4.2\n>Using Table 4.12 (p. 166), parenthesize the following expressions to\nindicate the order in which the operands are grouped:\n```cpp\n* vec.begin() //=> *(vec.begin())\n* vec.begin() + 1 //=> (*(vec.begin())) + 1\n```\n\n## Exercise 4.3\n>Order of evaluation for most of the binary operators is left\nundefined to give the compiler opportunities for optimization.\nThis strategy presents a trade-off between efficient code generation\nand potential pitfalls in the use of the language by the programmer.\nDo you consider that an acceptable trade-off? Why or why not?\n\nNo. IMHO, such design cannot improve performance siginificantly, but it can make bugs very tricky to handle.\n\n## Exercise 4.4\n>Parenthesize the following expression to show how it is evaluated.\nTest your answer by compiling the expression (without parentheses)\nand printing its result.\n```cpp\n12 / 3 * 4 + 5 * 15 + 24 % 4 / 2\n// parenthesize\n((12/3)*4) + (5*15) + ((24%4)/2)\n// 16 + 75 + 0 = 91\n// print: 91\n```\n\n## Exercise 4.5\n>Determine the result of the following expressions.\n```cpp\n-30 * 3 + 21 / 5  // -90+4 = -86\n-30 + 3 * 21 / 5  // -30+63/5 = -30+12 = -18\n30 / 3 * 21 % 5   // 10*21%5 = 210%5 = 0\n-30 / 3 * 21 % 4  // -10*21%4 = -210%4 = -2\n```\n\n## Exercise 4.6\n>Write an expression to determine whether an int value is even or odd.\n\n```cpp\n i & 0x1 \n```\n\n## Exercise 4.7\n>What does overflow mean? Show three expressions that will overflow.\n\nfrom the book:\n>Some arithmetic expressions yield undefined results. Some of these undefined espressions are due to the nature of mathematics-for example, division by zero. Others are undefined due to the nature of computers-for example, due to overflow. Overflow happens when a value is computed that is outside the range of values that the type can represent.\n\n```cpp\nshort svalue = 32767; ++svalue; // -32768\nunsigned uivalue = 0; --uivalue;  // 4294967295\nunsigned short usvalue = 65535; ++usvalue;  // 0\n```\n\n## Exercise 4.8\n>Explain when operands are evaluated in the logical `AND`, logical `OR`, and equality operators.\n\nfrom the book:\n> The logical `AND` and `OR` operators always evaluate their left operand before the right. Moreover, the right operand is evaluated if and only if the left operand does not determine the result. This strategy is known as **short-circuit evaluation**.\n\n- logical `AND` : the second operand is evaluated if and only if the left side is `true`.\n- logical `OR`  : the second operand is evaluated if and only if the left side is `false`\n- equality operators `==` : undefined.\n\n## Exercise 4.9\n>Explain the behavior of the condition in the following if:\n```cpp\nconst char *cp = \"Hello World\";\nif (cp && *cp)\n```\n\ncp is a pointer to `const char *`, and it's not a nullptr. true.\n\n`*cp` is a const char: 'H', and it is explicit a nonzero value. true.\n\ntrue && true -> true.\n\n## Exercise 4.10\n>Write the condition for a while loop that would read ints from\nthe standard input and stop when the value read is equal to 42.\n\n```cpp\nint i = 0;\nwhile(cin >> i && i != 42)\n```\n\n## Exercise 4.11\n>Write an expression that tests four values, a, b, c, and d,\nand ensures that a is greater than b, which is greater than c,\nwhich is greater than d.\n\n```cpp\na>b && b>c && c>d\n```\n\n## Exercise 4.12\n>Assuming `i`, `j`, and `k` are all ints, explain what `i != j < k` means.\n\n`i != j < k` is equivalent to `i != (j < k)`.\n\n\n## Exercise 4.13\n>What are the values of i and d after each assignment?\n```cpp\nint i;   double d;\nd = i = 3.5; // i = 3, d = 3.0\ni = d = 3.5; // d = 3.5, i = 3\n```\n\n## Exercise 4.14\n>Explain what happens in each of the if tests:\n```cpp\nif (42 = i)   // compile error: expression is not assignable\nif (i = 42)   // true.\n```\n\n## Exercise 4.15\n>The following assignment is illegal. Why? How would you correct it?\n```cpp\ndouble dval; int ival; int *pi;\ndval = ival = pi = 0;\n// pi is a pointer to int.\n// can not assign to 'int' from type 'int *'\n// correct it:\ndval = ival = 0;\npi = 0;\n```\n\n## Exercise 4.16\n>Although the following are legal,\nthey probably do not behave as the programmer expects. Why?\nRewrite the expressions as you think they should be.\n```cpp\nif (p = getPtr() != 0)\nif (i = 1024)\n// why? always true. use an assigment as a condition.\n// correct it\nif ((p=getPtr()) != 0)\nif (i == 1024)\n```\n\n## Exercise 4.17\n>Explain the difference between prefix and postfix increment.\n\nSee: [What is the difference between ++i and i++](http://stackoverflow.com/questions/24853/what-is-the-difference-between-i-and-i)\n\n## Exercise 4.18\n>What would happen if the while loop on page 148 that prints\nthe elements from a vector used the prefix increment operator?\n\nIt will print from the second element and dereference `v.end()` at last, which is a **UB**.\n\n## Exercise 4.19\n>Given that ptr points to an int, that vec is a vector<int>,\nand that ival is an int, explain the behavior of each of these expressions.\nWhich, if any, are likely to be incorrect? Why? How might each be corrected?\n\n```cpp\nptr != 0 && *ptr++  // check ptr is not a nullptr, and then check the pointer value.\nival++ && ival // check ival, and then check ival+1 whether equal zero.\nvec[ival++] <= vec[ival] // incorrect. It is an **undefined behavior.**\n// correct:\nvec[ival] <= vec[ival+1]\n```\n\nSee [order of evaluation](http://en.cppreference.com/w/cpp/language/eval_order).\n\n## Exercise 4.20\n>Assuming that iter is a vector<string>::iterator,\nindicate which, if any, of the following expressions are legal.\nExplain the behavior of the legal expressions and\nwhy those that aren’t legal are in error.\n```cpp\n*iter++;  // return *iter, then ++iter.\n(*iter)++;  // illegal, *iter is a string, cannot increment the value.\n*iter.empty() // illegal, iter should use '->' to indicate whether empty.\niter->empty();  // indicate the iter' value whether empty.\n++*iter;        // illegal, string have not increment.\niter++->empty();  // return iter->empty(), then ++iter.\n```\n\n## [Exercise 4.21](ex4_21.cpp)\n## [Exercise 4.22](ex4_22.cpp)\n## Exercise 4.23\n>The following expression fails to compile due to operator precedence.\nUsing Table 4.12 (p. 166), explain why it fails. How would you fix it?\n```cpp\nstring s = \"word\";\nstring pl = s + s[s.size() - 1] == 's' ? \"\" : \"s\" ;\n```\n\nOperator Precedence: `?:` < `+`\nFix it:\n```cpp\nstring pl = s + (s[s.size() - 1] == 's' ? \"\" : \"s\") ;\n```\n\n## Exercise 4.24\n>Our program that distinguished between high pass, pass,\nand fail depended on the fact that\nthe conditional operator is right associative.\nDescribe how that operator would be evaluated\nif the operator were left associative.\n\nif the operator were left associative.\n```cpp\nfinalgrade = (grade > 90) ? \"high pass\" : (grade < 60) ? \"fail\" : \"pass\";\n```\nwould same as :\n```cpp\nfinalgrade = ((grade > 90) ? \"high pass\" : (grade < 60)) ? \"fail\" : \"pass\";\n```\nif `grade > 90`, first conditional operator's result is `high pass`. so the finalgrade is always fail.\nIt's contradictory obviously.\n\n## Exercise 4.25\n>What is the value of ~'q' << 6 on a machine with 32-bit ints and 8 bit chars, that uses Latin-1 character set in which 'q' has the bit pattern 01110001?\n\nThe final value in decimal is `-7296`.  \n\n## Exercise 4.26\n>In our grading example in this section, what would happen if we used unsigned int as the type for quiz1?\n\nThe C++ standard does not specify the size of integral types in bytes, but it specifies minimum ranges they must be able to hold. The minimum range of `unsigned int` is 0 to 65535. Since some implementations use only the minimum 16 bits for `unsigned int`, this could cause undefined behavior.\n\n\n## Exercise 4.27\n>What is the result of each of these expressions?\n```cpp\nunsigned long ul1 = 3, ul2 = 7;\nul1 & ul2 // == 3\nul1 | ul2 // == 7\nul1 && ul2 // == true\nul1 || ul2 // == true\n```\n\n## [Exercise 4.28](ex4_28.cpp)\n## Exercise 4.29\n>Predict the output of the following code and explain your reasoning. Now run the program. Is the output what you expected? If not, figure out why.\n```cpp\nint x[10];   int *p = x;\ncout << sizeof(p)/sizeof(*p) << endl;\ncout << sizeof(x)/sizeof(*x) << endl;\n```\n\n * The first is 10. It returns the number of elements in x. \n * The second result is undefined.\n\n-----\nreference: [Why the size of a pointer is 4bytes in C++](http://stackoverflow.com/a/2428809)\n\n## Exercise 4.30\n>Using Table 4.12 (p. 166), parenthesize the following expressions to match the default evaluation:\n```cpp\nsizeof x + y      // (sizeof x)+y . \"sizeof\" has higher precedence than binary `+`.\nsizeof p->mem[i]  // sizeof(p->mem[i])\nsizeof a < b      // sizeof(a) < b\nsizeof f()        //If `f()` returns `void`, this statement is undefined, otherwise it returns the size of return type.\n```\n\n-----\nreference: [sizeof operator](http://en.cppreference.com/w/cpp/language/sizeof)\n\n## Exercise 4.31\n>The program in this section used the prefix increment and decrement operators. Explain why we used prefix and not postfix. What changes would have to be made to use the postfix versions? Rewrite the program using postfix operators.\n\n~~postfix will copy itself as return, then increment or decrement. prefix will increment or decrement first, and return itself. so prefix is more effective in this program.(reduce one copy space.)~~\n\nWe use prefix and not postfix, just because of the `Advice: Use Postfix Operators only When Necessary` on `§4.5. Increment and Decrement Operators`.\n\n>**Advice: Use Postfix Operators only When Necessary**\n\n>Readers from a C background might be surprised that we use the prefix increment in the programs we've written. The reason is simple: The prefix version avoids unnecessary work. It increments the value and returns the incremented version.The postfix operator must store the original value so that it can return the unincremented value as its result. If we don’t need the unincremented value, there’s no need for the extra work done by the postfix operator.\n\n>For ints and pointers, the compiler can optimize away this extra work. For more complicated iterator types, this extra work potentially might be more costly. By habitually using the prefix versions, we do not have to worry about whether the performance difference matters. Moreover—and perhaps more importantly—we can express the intent of our programs more directly.\n\nSo, it's just a good habits. And there are no changes if we have to be made to use the postfix versions. Rewrite:\n```cpp\nfor(vector<int>::size_type ix = 0; ix != ivec.size(); ix++, cnt--)  \n    ivec[ix] = cnt;\n```\n\nThis is not an appropriate example to discuss the difference of prefix and postfix. Look at the section `Built-in comma operator` on [this page](http://en.cppreference.com/w/cpp/language/operator_other).\n\n-----\nreference: [Usage of the Built-in Comma Operator](http://stackoverflow.com/questions/22591387/usage-of-the-built-in-comma-operator)\n\n## Exercise 4.32\n>Explain the following loop.\n```cpp\nconstexpr int size = 5;\nint ia[size] = { 1, 2, 3, 4, 5 };\nfor (int *ptr = ia, ix = 0;\n    ix != size && ptr != ia+size;\n    ++ix, ++ptr) { /* ... */ }\n```\n\n`ptr` and `ix` have the same function. The former use a pointer, and the latter use the index of array. we use the loop to through the array.(just choose one from `ptr` and `ix`)\n\n## Exercise 4.33\n>Using Table 4.12 (p. 166) explain what the following expression does:\n```cpp\nsomeValue ? ++x, ++y : --x, --y\n```\n\nBecause of the most lowest precedence of the comma operator, the expression is same as:\n```cpp\n(someValue ? ++x, ++y : --x), --y\n```\nIf someValue is true, then `++x`, and the result is `y`, if someValue is false, then `--x`, and the result is `--y`. so it is also same as:\n```cpp\nsomeValue ? (++x, y) : (--x, --y);\n```\nEven though the result has nothing to do with `x`, the evaluation of `someValue` does effect the operation on `x`.\n\n## Exercise 4.34\n>Given the variable definitions in this section, explain what conversions take place in the following expressions:\n(a) if (fval)\n(b) dval = fval + ival;\n(c) dval + ival * cval;\nRemember that you may need to consider the associativity of the operators.\n\n```cpp\nif (fval) // fval converted to bool\ndval = fval + ival; // ival converted to fval, then the result of fval add ival converted to double.\ndval + ival * cval; // cval converted to int, then that int and ival converted to double.\n```\n\n## Exercise 4.35\n>Given the following definitions,\n```cpp\nchar cval; int ival; unsigned int ui; float fval; double dval;\n```\nidentify the implicit type conversions, if any, taking place:\n```cpp\ncval = 'a' + 3; // 'a' promoted to int, then the result of ('a' + 3)(int) converted to char.\nfval = ui - ival * 1.0; // ival converted to double , ui also converted to double. then that double converted(by truncation) to float.\ndval = ui * fval; // ui promoted to float. then that float converted to double.\ncval = ival + fval + dval;  // ival converted to float, then that float and fval converted to double. At last, that double converted to char(by truncation).\n```\n\n## Exercise 4.36\n>Assuming i is an int and d is a double write the expression i *= d so that it does integral, rather than floating-point, multiplication.\n\n```cpp\ni *= static_cast<int>(d);\n```\n\n## Exercise 4.37\n>Rewrite each of the following old-style casts to use a named cast:\n```cpp\nint i; double d; const string *ps; char *pc; void *pv;\npv = (void*)ps; // pv = const_cast<string*>(ps); or pv = static_cast<void*>(const_cast<string*>(ps));\ni = int(*pc);   // i = static_cast<int>(*pc);\npv = &d;        // pv = static_cast<void*>(&d);\npc = (char*)pv; // pc = static_cast<char*>(pv);\n```\n\n## Exercise 4.38\n>Explain the following expression:\n```cpp\ndouble slope = static_cast<double>(j/i);\n```\n\nj/i is an int(by truncation), then converted to double and assigned to slope.\n"
  },
  {
    "path": "ch04/ex4_21.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nusing std::cout;\nusing std::endl;\nusing std::vector;\n\nint main()\n{\n    vector<int> ivec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\n    for (auto i : ivec) {\n        cout << ((i & 0x1) ? i * 2 : i) << \" \";\n    }\n    cout << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch04/ex4_22.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::cin; using std::endl;\n\nint main()\n{\n    for (unsigned g; cin >> g; )\n    {\n        // conditional operators\n        auto result = g > 90 ? \"high pass\" : g < 60 ? \"fail\" : g < 75 ? \"low pass\" : \"pass\";\n        cout << result << endl;\n\n        // if statements\n        if (g > 90)         cout << \"high pass\";\n        else if (g < 60)    cout << \"fail\";\n        else if (g < 75)    cout << \"low pass\";\n        else                cout << \"pass\";\n        cout << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch04/ex4_28.cpp",
    "content": "#include <iostream> // high level input/output operations.\n\nint main()\n{\n    // by using method below only include what is needed.\n    using std::cout;\n    using std::endl;\n    \n    // void type\n    cout << \"void: nullptr_t\\t\" << sizeof(std::nullptr_t) << \" bytes\" << endl << endl;\n    \n    // boolean type\n    cout << \"bool:\\t\\t\" << sizeof(bool) << \" bytes\" << endl << endl;\n    \n    // character type\n    cout << \"char:\\t\\t\" << sizeof(char) << \" bytes\" << endl;\n    cout << \"wchar_t:\\t\" << sizeof(wchar_t) << \" bytes\" << endl;\n    cout << \"char16_t:\\t\" << sizeof(char16_t) << \" bytes\" << endl;\n    cout << \"char32_t:\\t\" << sizeof(char32_t) << \" bytes\" << endl << endl;\n    \n    // integers type\n    cout << \"short:\\t\\t\" << sizeof(short) << \" bytes\" << endl;\n    cout << \"int:\\t\\t\" << sizeof(int) << \" bytes\" << endl;\n    cout << \"long:\\t\\t\" << sizeof(long) << \" bytes\" << endl;\n    cout << \"long long:\\t\" << sizeof(long long) << \" bytes\" << endl << endl;\n    \n    // floating point type\n    cout << \"float:\\t\\t\" << sizeof(float) << \" bytes\" << endl;\n    cout << \"double:\\t\\t\" << sizeof(double) << \" bytes\" << endl;\n    cout << \"long double:\\t\" << sizeof(long double) << \" bytes\" << endl << endl;\n\t\n    // Fixed width integers\n    cout << \"int8_t:\\t\\t\" << sizeof(int8_t) << \" bytes\" << endl;\n    cout << \"uint8_t:\\t\" << sizeof(uint8_t) << \" bytes\" << endl;\n    cout << \"int16_t:\\t\" << sizeof(int16_t) << \" bytes\" << endl;\n    cout << \"uint16_t:\\t\" << sizeof(uint16_t) << \" bytes\" << endl;\n    cout << \"int32_t:\\t\" << sizeof(int32_t) << \" bytes\" << endl;\n    cout << \"uint32_t:\\t\" << sizeof(uint32_t) << \" bytes\" << endl;\n    cout << \"int64_t:\\t\" << sizeof(int64_t) << \" bytes\" << endl;\n    cout << \"uint64_t:\\t\" << sizeof(uint64_t) << \" bytes\" << endl;\n    \t\n    return 0;\n}\n"
  },
  {
    "path": "ch05/README.md",
    "content": "## Exercise 5.1\n>What is a null statement? When might you use a null statement?\n\nA null statement is the empty statement. like this:\n```cpp\n; // null statement\n```\n\nThe null statement may be used as a placeholder when a statement is expected. For example:\n```cpp\n// read until we hit end-of-file or find an input equal to sought\nwhile (cin >> s && s != sought)\n    ; // null statement.\n```\n\n## Exercise 5.2\n>What is a block? When might you might use a block?\n\nA block is a (possibly empty) sequence of statements and declarations surrounded by a pair of curly braces.It's used when multiple statements are needed.For example:\n```cpp\nwhile (val <= 10)\n{\n    sum += val;\n    ++val;\n}\n```\n\n## Exercise 5.3\n>Use the comma operator (§ 4.10, p. 157) to rewrite the while loop from § 1.4.1 (p. 11)\nso that it no longer requires a block.\nExplain whether this rewrite improves or diminishes the readability of this code.\n\n```cpp\n#include <iostream>\nint main()\n{\n    int sum = 0, val = 1;\n    while (val <= 10)\n        sum += val, ++val;\n    std::cout << \"Sum of 1 to 10 inclusive is \" << sum << std::endl;\n\n    return 0;\n}\n```\n\nThis rewritten version diminishes the readability. \n\n## Exercise 5.4\n>Explain each of the following examples, and correct any problems you detect.\n- (a) while (string::iterator iter != s.end()) { /* . . . */ }\n- (b) while (bool status = find(word)) { /* . . . */ } if (!status) { /* . . . */ }\n\n(a) Illegal declaration : `string::iterator iter != s.end()`\n```cpp\n//corrrected as:\nstd::string::iterator iter = s.begin();\nwhile (iter != s.end()) { /* . . . */ }\n```\n\n(b) Variable `status` is only declared inside scope of while condition.\n```cpp\n//corrrected as:\nbool status;\nwhile (status = find(word)) { /* ... */ }\nif (!status) { /* ... */ }\n```  \n\n## [Exercise 5.5](ex5_5.cpp)\n## [Exercise 5.6](ex5_6.cpp)\n## Exercise 5.7\n>Correct the errors in each of the following code fragments:\n```cpp\n(a) if (ival1 != ival2) ival1 = ival2\n    else ival1 = ival2 = 0;\n(b) if (ival < minval) minval = ival;\n    occurs = 1;\n(c) if (int ival = get_value())\n    cout << \"ival = \" << ival << endl;\n    if (!ival)\n    cout << \"ival = 0\\n\";\n(d) if (ival = 0)\n    ival = get_value();\n```\n\n```cpp\n(a) if (ival1 != ival2) ival1 = ival2;  // Need to add semicolon.\n    else ival1 = ival2 = 0;\n(b) if (ival < minval)                  // Braces needed to include both satetments in scope.\n    {\n        minval = ival;\n        occurs = 1;\n    }\n(c) if (int ival = get_value())         //Second if statement should be else-if.\n        cout << \"ival = \" << ival << endl;\n    else if (!ival)\n        cout << \"ival = 0\\n\";\n(d) if (ival == 0)                      //Expression changed from assignment to \"equal to\";\n    ival = get_value();\n```\n\n## Exercise 5.8\n>What is a “dangling else”? How are else clauses resolved in C++?\n\nColloquial term used to refer to the problem of how to process nested if statements in which there are more ifs than elses. In C++, an else is always paired with the closest preceding unmatched if.\n\n## [Exercise 5.9](ex5_9.cpp)\n## [Exercise 5.10](ex5_10.cpp)\n## [Exercise 5.11](ex5_11.cpp)\n## [Exercise 5.12](ex5_12.cpp)\n\n## Exercise 5.13\n>Each of the programs in the highlighted text on page 184 contains a common programming error. Identify and correct each error.\n```cpp\n(a) unsigned aCnt = 0, eCnt = 0, iouCnt = 0;\n    char ch = next_text();\n    switch (ch) {\n        case 'a': aCnt++;\n        case 'e': eCnt++;\n        default: iouCnt++;\n    }\n(b) unsigned index = some_value();\n    switch (index) {\n        case 1:\n            int ix = get_value();\n            ivec[ ix ] = index;\n            break;\n        default:\n            ix = ivec.size()-1;\n            ivec[ ix ] = index;\n    }\n(c) unsigned evenCnt = 0, oddCnt = 0;\n    int digit = get_num() % 10;\n    switch (digit) {\n        case 1, 3, 5, 7, 9:\n            oddcnt++;\n            break;\n        case 2, 4, 6, 8, 10:\n            evencnt++;\n            break;\n    }\n(d) unsigned ival=512, jval=1024, kval=4096;\n    unsigned bufsize;\n    unsigned swt = get_bufCnt();\n    switch(swt) {\n        case ival:\n            bufsize = ival * sizeof(int);\n            break;\n        case jval:\n            bufsize = jval * sizeof(int);\n            break;\n        case kval:\n            bufsize = kval * sizeof(int);\n            break;\n    }\n```\n\n```cpp\n(a) // Error: should have a break statement\n    unsigned aCnt = 0, eCnt = 0, iouCnt = 0;\n    char ch = next_text();\n    switch (ch) {\n        case 'a': aCnt++; break;\n        case 'e': eCnt++; break;\n        default : iouCnt++; break;\n    }\n(b) // Error: control bypass an explicitly initialized variable ix.\n    unsigned index = some_value();\n    int ix;\n    switch (index) {\n        case 1:\n            ix = get_value();\n            ivec[ ix ] = index;\n            break;\n        default:\n            ix = static_cast<int>(ivec.size())-1;\n            ivec[ ix ] = index;\n    }\n(c) // Error: case label syntax error\n    unsigned evenCnt = 0, oddCnt = 0;\n    int digit = get_num() % 10;\n    switch (digit) {\n        case 1: case 3: case 5: case 7: case 9:\n            oddcnt++; // oddcnt != oddCnt\n            break;\n        case 2: case 4: case 6: case 8: case 0:\n            evencnt++; // evencnt != evenCnt\n            break;\n    }\n(d) // Error: case label must be a constant expression\n    const unsigned ival=512, jval=1024, kval=4096;\n    unsigned bufsize;\n    unsigned swt = get_bufCnt();\n    switch(swt) {\n        case ival:\n            bufsize = ival * sizeof(int);\n            break;\n        case jval:\n            bufsize = jval * sizeof(int);\n            break;\n        case kval:\n            bufsize = kval * sizeof(int);\n            break;\n    }\n```\n\n## Exercise 5.14\n>Write a program to read strings from standard input looking for duplicated words. The program should find places in the input where one word is followed immediately by itself. Keep track of the largest number of times a single repetition occurs and which word is repeated. Print the maximum number of duplicates, or else print a message saying that no word was repeated. For example, if the input is\n```sh\nhow now now now brown cow cow\n```\nthe output should indicate that the word now occurred three times.\n\n- [concise solution](ex5_14.cpp)\n\n\n## Exercise 5.15\n>Explain each of the following loops. Correct any problems you detect.\n```cpp\n(a) for (int ix = 0; ix != sz; ++ix) { /* ... */ }\n    if (ix != sz)\n    // . . .\n(b) int ix;\n    for (ix != sz; ++ix) { /* ... */ }\n(c) for (int ix = 0; ix != sz; ++ix, ++sz) { /*...*/ }\n```\n\n```cpp\n(a) int ix;\n    for (ix = 0; ix != sz; ++ix)  { /* ... */ }\n    if (ix != sz)\n    // . . .\n(b) int ix;\n    for (; ix != sz; ++ix) { /* ... */ }\n(c) for (int ix = 0; ix != sz; ++ix) { /*...*/ }\n```\n\n## Exercise 5.16\n>The while loop is particularly good at executing while some condition holds; for example, when we need to read values until end-of-file. The for loop is generally thought of as a **step loop**: An index steps through a range of values in a collection. Write an idiomatic use of each loop and then rewrite each using the other loop construct. If you could use only one loop, which would you choose? Why?\n\n```cpp\n// while idiomatic\nint i;\nwhile ( cin >> i )\n    // ...\n\n// same as for\nfor (int i = 0; cin >> i;)\n    // ...\n\n// for idiomatic\nfor (int i = 0; i != size; ++i)\n    // ...\n\n// same as while\nint i = 0;\nwhile (i != size)\n{\n    // ...\n    ++i;\n}\n```\n\nI prefer `for` to `while` in such cases, because it's terse. More importantly, object i won't pollute the external scope after it goes out of the loop. It's a little bit easier to add new code into the external scope, since it reduces the possibility of naming conflicts .That is, a higher maintainability. Of course, this way makes the code a bit harder to read. ([@Mooophy](https://github.com/Mooophy))\n\n## [Exercise 5.17](ex5_17.cpp)\n\n## Exercise 5.18\n>Explain each of the following loops. Correct any problems you detect.\n```cpp\n(a) do { // added bracket.\n        int v1, v2;\n        cout << \"Please enter two numbers to sum:\" ;\n        if (cin >> v1 >> v2)\n            cout << \"Sum is: \" << v1 + v2 << endl;\n    }while (cin);\n(b) int ival;\n    do {\n        // . . .\n    } while (ival = get_response()); // should not declared in this scope.\n(c) int ival = get_response();\n    do {\n        ival = get_response();\n    } while (ival); // ival is not declared in this scope.\n```\n\n## [Exercise 5.19](ex5_19.cpp)\n## [Exercise 5.20](ex5_20.cpp)\n## [Exercise 5.21](ex5_21.cpp)\n\n## Exercise 5.22\n>The last example in this section that jumped back to begin could be better written using a loop. Rewrite the code to eliminate the goto.\n```cpp\n// backward jump over an initialized variable definition is okay  \nbegin:\n    int sz = get_size();\n    if (sz <= 0) {\n        goto begin;\n    }\n```\n\nuse `for` to replace `goto`:\n```cpp\nfor (int sz = get_size(); sz <=0; sz = get_size())\n    ; // should not remove.\n```\n\n## [Exercise 5.23](ex5_23.cpp)\n## [Exercise 5.24](ex5_24.cpp)\n## [Exercise 5.25](ex5_25.cpp)\n"
  },
  {
    "path": "ch05/ex5_10.cpp",
    "content": "#include <iostream>\nusing std::cin; using std::cout; using std::endl;\n\nint main()\n{\n    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;\n    char ch;\n    while (cin >> ch)\n        switch (ch)\n        {\n            case 'a':\n            case 'A':\n                ++aCnt;\n                break;\n            case 'e':\n            case 'E':\n                ++eCnt;\n                break;\n            case 'i':\n            case 'I':\n                ++iCnt;\n                break;\n            case 'o':\n            case 'O':\n                ++oCnt;\n                break;\n            case 'u':\n            case 'U':\n                ++uCnt;\n                break;\n        }\n           \n    cout << \"Number of vowel a(A): \\t\" << aCnt << '\\n'\n         << \"Number of vowel e(E): \\t\" << eCnt << '\\n'\n         << \"Number of vowel i(I): \\t\" << iCnt << '\\n'\n         << \"Number of vowel o(O): \\t\" << oCnt << '\\n'\n         << \"Number of vowel u(U): \\t\" << uCnt << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_11.cpp",
    "content": "#include <iostream>\n\nusing std::cin; using std::cout; using std::endl;\n\nint main()\n{\n    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0, spaceCnt = 0, tabCnt = 0, newLineCnt = 0;\n    char ch;\n    while (cin >> std::noskipws >> ch)\n        switch (ch)\n        {\n            case 'a':\n            case 'A':\n                ++aCnt;\n                break;\n            case 'e':\n            case 'E':\n                ++eCnt;\n                break;\n            case 'i':\n            case 'I':\n                ++iCnt;\n                break;\n            case 'o':\n            case 'O':\n                ++oCnt;\n                break;\n            case 'u':\n            case 'U':\n                ++uCnt;\n                break;\n            case ' ':\n                ++spaceCnt;\n                break;\n            case '\\t':\n                ++tabCnt;\n                break;\n            case '\\n':\n                ++newLineCnt;\n                break;\n        }\n    \n    cout << \"Number of vowel a(A): \\t\" << aCnt << '\\n'\n        << \"Number of vowel e(E): \\t\" << eCnt << '\\n'\n        << \"Number of vowel i(I): \\t\" << iCnt << '\\n'\n        << \"Number of vowel o(O): \\t\" << oCnt << '\\n'\n        << \"Number of vowel u(U): \\t\" << uCnt << '\\n'\n        << \"Number of space: \\t\" << spaceCnt << '\\n'\n        << \"Number of tab char: \\t\" << tabCnt << '\\n'\n        << \"Number of new line: \\t\" << newLineCnt << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_12.cpp",
    "content": "#include <iostream>\n\nusing std::cin; using std::cout; using std::endl;\n\nint main()\n{\n    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0, spaceCnt = 0, tabCnt = 0, newLineCnt = 0, ffCnt = 0, flCnt = 0, fiCnt = 0;\n    char ch, prech = '\\0';\n    while (cin >> std::noskipws >> ch)\n    {\n        switch (ch)\n        {\n            case 'a':\n            case 'A':\n                ++aCnt;\n                break;\n            case 'e':\n            case 'E':\n                ++eCnt;\n                break;\n            case 'i':\n                if (prech == 'f') ++fiCnt;\n            case 'I':\n                ++iCnt;\n                break;\n            case 'o':\n            case 'O':\n                ++oCnt;\n                break;\n            case 'u':\n            case 'U':\n                ++uCnt;\n                break;\n            case ' ':\n                ++spaceCnt;\n                break;\n            case '\\t':\n                ++tabCnt;\n                break;\n            case '\\n':\n                ++newLineCnt;\n                break;\n            case 'f':\n                if (prech == 'f') ++ffCnt;\n                break;\n            case 'l':\n                if (prech == 'f') ++flCnt;\n                break;\n        }\n        prech = ch;\n    }\n    \n    cout << \"Number of vowel a(A): \\t\" << aCnt << '\\n'\n        << \"Number of vowel e(E): \\t\" << eCnt << '\\n'\n        << \"Number of vowel i(I): \\t\" << iCnt << '\\n'\n        << \"Number of vowel o(O): \\t\" << oCnt << '\\n'\n        << \"Number of vowel u(U): \\t\" << uCnt << '\\n'\n        << \"Number of space: \\t\" << spaceCnt << '\\n'\n        << \"Number of tab char: \\t\" << tabCnt << '\\n'\n        << \"Number of new line: \\t\" << newLineCnt << '\\n'\n        << \"Number of ff: \\t\" << ffCnt << '\\n'\n        << \"Number of fl: \\t\" << flCnt << '\\n'\n        << \"Number of fi: \\t\" << fiCnt << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_14.cpp",
    "content": "#include <iostream>\n#include <string>\n\nusing std::cout; using std::cin; using std::endl; using std::string; using std::pair;\n\nint main()\n{ \n    pair<string, int> max_duplicated;\n    int count = 0;\n    for (string str, prestr; cin >> str; prestr = str)\n    {\n        if (str == prestr) ++count;\n        else count = 0; \n        if (count > max_duplicated.second) max_duplicated = { prestr, count };\n    }\n    \n    if (max_duplicated.first.empty()) cout << \"There's no duplicated string.\" << endl;\n    else cout << \"the word \" << max_duplicated.first << \" occurred \" << max_duplicated.second + 1 << \" times. \" << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_17.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nusing std::cout; using std::vector;\n\nbool is_prefix(vector<int> const& lhs, vector<int> const& rhs)\n{\n    if(lhs.size() > rhs.size())\n        return is_prefix(rhs, lhs);\n    for(unsigned i = 0; i != lhs.size(); ++i)\n        if(lhs[i] != rhs[i]) return false;\n    return true;\n}\n\nint main()\n{\n    vector<int> l{ 0, 1, 1, 2 };\n    vector<int> r{ 0, 1, 1, 2, 3, 5, 8 };\n    cout << (is_prefix(r, l) ? \"yes\\n\" : \"no\\n\");\n\n    return 0;\n}\n\n"
  },
  {
    "path": "ch05/ex5_19.cpp",
    "content": "#include <iostream>\n#include <string>\n\nusing std::cout; using std::cin; using std::endl; using std::string;\n\nint main()\n{\n    string rsp;\n    do {\n        cout << \"Input two strings: \";\n        string str1, str2;\n        cin >> str1 >> str2;\n        cout << (str1 <= str2 ? str1 : str2) \n             << \" is less than the other. \" << \"\\n\\n\"\n             << \"More? Enter yes or no: \";\n        cin >> rsp;\n    } while (!rsp.empty() && tolower(rsp[0]) == 'y');\n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_20.cpp",
    "content": "#include <iostream>\n#include <string>\nusing std::cout; using std::cin; using std::endl; using std::string;\n\nint main()\n{\n    string read, tmp;\n    while (cin >> read)\n        if (read == tmp) break; else tmp = read;\n\n    if (cin.eof())  cout << \"no word was repeated.\" << endl;\n    else            cout << read << \" occurs twice in succession.\" << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_21.cpp",
    "content": "//  @Brief   Revise the program from the exercise in 5.5.1(p. 191)\n//           so that it looks only for duplicated words that start with an uppercase letter. \n//  @See     Exercise 5.20\n//  @frank67 Rewrite using the 'continue' statement. See #250\n\n#include <iostream>\nusing std::cin; using std::cout; using std::endl;\n#include <string>\nusing std::string;\n\nint main()\n{\n    string curr, prev;\n    bool no_twice = true;\n    while (cin >> curr) \n    {\n        if (isupper(curr[0]) && prev == curr)\n        {\n            cout << curr << \": occurs twice in succession.\" << endl;\n            no_twice = false;\n            break;\n        }\n        prev = curr;\n    }\n\n    if (no_twice)\n        cout << \"no word was repeated.\" << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_23.cpp",
    "content": "#include <iostream>\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\nint main() \n{\n    int i, j; \n    cin >> i >> j;\n    cout << i / j << endl;\n \n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_24.cpp",
    "content": "#include <iostream>\n#include <stdexcept>\n\n//\n//  When a zero entered, the code below would crash with feedback as :\n//  \"Unhandled exception at 0x75834598 in just_for_cpp.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0054F9F4.\"\n//  \n//  Tested on Windows 8.1 + Vs 2013\n//\n\nint main(void)\n{\n    int i, j;\n    std::cin >> i >> j;\n    if (j == 0)\n        throw std::runtime_error(\"divisor is 0\");\n    std::cout << i / j << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_25.cpp",
    "content": "#include <iostream>\n#include <stdexcept>\nusing std::cin; using std::cout; using std::endl; using std::runtime_error;\n\nint main(void)\n{\n    for (int i, j; cout << \"Input two integers:\\n\", cin >> i >> j; )\n    {\n        try \n        {\n            if (j == 0) \n                throw runtime_error(\"divisor is 0\");\n            cout << i / j << endl;\n        }\n        catch (runtime_error err) \n        {\n            cout << err.what() << \"\\nTry again? Enter y or n\" << endl;\n            char c;\n            cin >> c;\n            if (!cin || c == 'n')\n                break;\n        }\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_5.cpp",
    "content": "#include <iostream>\n#include <vector>\n#include <string>\nusing std::vector; using std::string; using std::cout; using std::endl; using std::cin;\n\nint main()\n{\n    vector<string> scores = { \"F\", \"D\", \"C\", \"B\", \"A\", \"A++\" };\n    for (int g; cin >> g;)\n    {\n        string letter;\n        if (g < 60)\n        {\n            letter = scores[0];\n        }\n        else\n        {\n            letter = scores[(g - 50) / 10];\n            if (g != 100)\n                letter += g % 10 > 7 ? \"+\" : g % 10 < 3 ? \"-\" : \"\";\n        }\n        cout << letter << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_6.cpp",
    "content": "#include <iostream>\n#include <vector>\n#include <string>\nusing std::vector; using std::string; using std::cout; using std::endl; using std::cin;\n\nint main()\n{\n    vector<string> scores = { \"F\", \"D\", \"C\", \"B\", \"A\", \"A++\" };\n\n    int grade = 0;\n    while (cin >> grade)\n    {\n        string lettergrade = grade < 60 ? scores[0] : scores[(grade - 50) / 10];\n        lettergrade += (grade == 100 || grade < 60) ? \"\" : (grade % 10 > 7) ? \"+\" : (grade % 10 < 3) ? \"-\" : \"\";\n        cout << lettergrade << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch05/ex5_9.cpp",
    "content": "#include <iostream>\n\nusing std::cout; using std::endl; using std::cin;\n\nint main()\n{\n    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;\n    char ch;\n    while (cin >> ch)\n    {\n        if (ch == 'a') ++aCnt;\n        else if (ch == 'e') ++eCnt;\n        else if (ch == 'i') ++iCnt;\n        else if (ch == 'o') ++oCnt;\n        else if (ch == 'u') ++uCnt;\n    }\n    cout << \"Number of vowel a: \\t\" << aCnt << '\\n'\n        << \"Number of vowel e: \\t\" << eCnt << '\\n'\n        << \"Number of vowel i: \\t\" << iCnt << '\\n'\n        << \"Number of vowel o: \\t\" << oCnt << '\\n'\n        << \"Number of vowel u: \\t\" << uCnt << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch06/Chapter6.h",
    "content": "int fact(int val);\nint func();\n\ntemplate <typename T> \nT abs(T i)\n{\n    return i >= 0 ? i : -i;\n}\n"
  },
  {
    "path": "ch06/README.md",
    "content": "## Exercise 6.1\n\n**Parameters**: Local variable declared inside the function parameter list.\nthey are initialized by the **arguments** provided in the each function call.\n\n**Arguments**: Values supplied in a function call that are used to initialize the function's **parameters**.\n\n## Exercise 6.2\n```cpp\n(a) string f() {  // return should be string, not int\n          string s;\n          // ...\n          return s;\n    }\n(b) void f2(int i) { /* ... */ }  // function needs return type\n(c) int calc(int v1, int v2) { /* ... */ }  // parameter list cannot use same name twice\n(d) double square (double x) { return x * x; }  // function body needs braces\n```\n\n## Exercise 6.3\n\n```cpp\n#include <iostream>\n\nint fact(int i)\n{\n    if(i<0)\n    {\n        runtime_error err(\"Input cannot be a negative number\");\n        cout << err.what() << endl;\n    }\n    return i > 1 ? i * fact( i - 1 ) : 1;\n}\n\nint main()\n{\n    std::cout << std::boolalpha << (120 == fact(5)) << std::endl;\n    return 0;\n}\n```\n\n## Exercise 6.4\n\n```cpp\n#include <iostream>\n#include <string>\n\nint fact(int i)\n{\n    return i > 1 ? i * fact(i - 1) : 1;\n}\n\nvoid interactive_fact()\n{\n    std::string const prompt = \"Enter a number within [1, 13) :\\n\";\n    std::string const out_of_range = \"Out of range, please try again.\\n\";\n    for (int i; std::cout << prompt, std::cin >> i; )\n    {\n        if (i < 1 || i > 12)\n        {\n            std::cout << out_of_range; \n            continue;\n        }\n        std::cout << fact(i) << std::endl;\n    }\n}\n\nint main()\n{\n    interactive_fact();\n    return 0;\n}\n```\n\n## Exercise 6.5\n\n```cpp\n#include <iostream>\n\nint abs(int i)\n{\n    return i > 0 ? i : -i;\n}\n\nint main()\n{\n    std::cout << abs(-5) << std::endl;\n    return 0;\n}\n```\n\n## Exercise 6.6\n\n\n**local variable**: Variables defined inside a **block**;\n\n**parameter**: **Local variables** declared inside the **function parameter list**\n\n**local static variable**: **local static variable（object）** is initialized before the first time execution passes through the object’s definition.**Local statics** are not destroyed when a function ends; they are **destroyed when the program terminates.**\n\n```cpp\n// example\nsize_t count_add(int n)       // n is a parameter.\n{\n    static size_t ctr = 0;    // ctr is a static variable.\n    ctr += n;\n    return ctr;\n}\n\nint main()\n{\n    for (size_t i = 0; i != 10; ++i)  // i is a local variable.\n      cout << count_add(i) << endl;\n\n    return 0;\n}\n```\n\n## Exercise 6.7\n\n```cpp\nsize_t generate()\n{\n    static size_t ctr = 0;\n    return ctr++;\n}\n```\n\n## [Exercise 6.8](Chapter6.h)\n## Exercise 6.9 [fact.cc](fact.cc) | [factMain.cc](factMain.cc)\n## [Exercise 6.10](ex6_10.cpp)\n## [Exercise 6.11](ex6_11.cpp)\n## [Exercise 6.12](ex6_12.cpp)\n## Exercise 6.13\n\n`void f(T)` pass the argument by value. **nothing the function does to the parameter can affect the argument**.\n`void f(T&)` pass a reference, will be **bound to** whatever T object we pass.\n\n## Exercise 6.14\n\na parameter should be a reference type:\n```cpp\nvoid reset(int &i)\n{\n        i = 0;\n}\n```\n\na parameter should not be a reference:\n```cpp\nvoid print(std::vector<int>::iterator begin, std::vector<int>::iterator end)\n{\n        for (std::vector<int>::iterator iter = begin; iter != end; ++iter)\n                std::cout << *iter << std::endl;\n}\n```\n\n## Exercise 6.15\n\n>why is `s` a reference to const but `occurs` is a plain reference?\n\nBecause `s` should not be changed by this function, but `occurs` result must be calculated by the function.\n\n>Why are these parameters references, but the char parameter `c` is not?\n\nBecause `c` may be a temp varable, such as `find_char(s, 'a', occurs)`\n\n>What would happen if we made `s` a plain reference? What if we made `occurs` a reference to const?\n\n`s` could be changed in the function, and `occurs` would not be changed. so `occurs = 0;` is an error.\n\n## Exercise 6.16\n```cpp\nbool is_empty(const string& s) { return s.empty(); }\n```\n\nSince this function doesn't change the argument, \"const\" shoud be added\nbefore string&s, otherwise this function is misleading and can't be used\nwith const string or in a const function.\n\n## [Exercise 6.17](ex6_17.cpp)\n\nNot the same.\nFor the first one \"const\" was used, since no change need to do for the argument.\nFor the second function, \"const\" can't be used, because the content of the agument\nshould be changed.\n\n## Exercise 6.18\n(a)\n```cpp\nbool compare(const matrix &m1, cosnt matrix &m2);\n```\n(b)\n```cpp\nvector<int>::iterator change_val(int num, vector<int>::iterator &it);\n```\n\n## Exercise 6.19\n\n(a) illegal, only one parameter.\n(b) legal.\n(c) legal.\n(d) legal.\n\n## Exercise 6.20\n\nIf we can use `const`, just use it. If we make a parameter a plain reference when it could be a reference to `const`,\nthe reference value maybe changed.\n\n## [Exercise 6.21](ex6_21.cpp)\n## [Exercise 6.22](ex6_22.cpp)\n## [Exercise 6.23](ex6_23.cpp)\n\n## Exercise 6.24\n\n>Arrays have two special properties that affect how we define and use functions that operate on arrays: We cannot copy an array, and when we use an array it is (usually) **converted to a pointer**.\n\nSo we cannot pass an array by value, and when we pass an array to a function, we are actually passing a pointer\nto the array's first element.\n\nIn this question, `const int ia[10]` is actually same as `const int*`, and the size of the array is **irrelevant**.\nwe can pass `const int ia[3]` or `const int ia[255]`, there are no differences. If we want to pass an array which size is ten, we should use reference like that:\n```cpp\nvoid print10(const int (&ia)[10]) { /*...*/ }\n```\n\nsee more discusses at http://stackoverflow.com/questions/26530659/confused-about-array-parameters\n\n## [Exercise 6.25 && Exercise 6.26](ex6_25_26.cpp)\n## [Exercise 6.27](ex6_27.cpp)\n\n## Exercise 6.28\n\nThe type of `elem` in the `for` loop is `const std::string&`.\n\n## Exercise 6.29\n\nDepends on the type of elements of `initializer_list`. When the type is [PODType](http://en.cppreference.com/w/cpp/concept/PODType), reference is unnecessary. Because `POD` is **cheap to copy**(such as `int`). Otherwise, Using reference(`const`) is the better choice.\n\n## Exercise 6.30\n\nError (Clang):\n>Non-void function 'str_subrange' should return a value. // error #1\n\n>Control may reach end of non-void function. // error #2\n\n## Exercise 6.31\n\nwhen you can find the preexisting object that the reference refered.\n\n## Exercise 6.32\n\nlegal, it gave the values (0 ~ 9) to array `ia`.\n\n## [Exercise 6.33](ex6_33.cpp)\n## Exercise 6.34\n\nWhen the recursion termination condition becomes `var != 0`, two situations can happen :\n* case 1 : If the argument is positive, recursion stops at 0.(Note : There is one extra multiplication step though as the combined expression for factorial(5) reads 5 * 4 * 3 * 2 * 1 * 1. In terms of programming languages learning, such subtle difference probably looks quite trivial. In algorithms analysis and proof, however, this extra step may be super important.)\n* case 2 : if the argument is negative, recursion would never stop. As a result, a stack overflow would occur.\n\n## Exercise 6.35\n\nthe recursive function will always use `val` as the parameter. *a recursion loop* would happen.\n\n## Exercise 6.36\n\n```cpp\nstring (&func())[10]\n```\n\n## Exercise 6.37\n\n```cpp\n// type alias\nusing ArrT = string[10];\nArrT& func1();\n\n// trailing return\nauto func2() -> string(&)[10];\n\n// decltype\nstring arrS[10];\ndecltype(arrS)& func3();\n```\n\nI pefer the first one. because it is more simpler to me.\n\n## Exercise 6.38\n```cpp\ndecltype(arrStr)& arrPtr(int i)\n{\n          return (i % 2) ? odd : even;\n}\n```\n\n## Exercise 6.39\n\n(a) legal, repeated declarations(without definition) are legal in C++\n\n(b) illegal, only the return type is different\n\n(c) legal, the parameter type is different and return type is changed\n\n## Exercise 6.40\n\n(a) no error\n\n(b) Missing default argument on parameter 'wd', 'bckgrnd'.\n\n## Exercise 6.41\n\n(a) illegal. No matching function for call to 'init'.\n\n(b) legal, and match.\n\n(c) legal, but not match. `wd` whould be setting to '*'.\n\n## [Exercise 6.42](ex6_42.cpp)\n## Exercise 6.43\n\nBoth two should put in a header. (a) is an inline function. (b) is the declaration of useful function. we always put them in the header.\n\n## [Exercise 6.44](ex6_44.cpp)\n## Exercise 6.45\n\nFor example, the function `arrPtr` in [Exercise 6.38](# Exercise-638) and `make_plural` in [Exercise 6.42](# Exercise-642) should be defined as `inline`. But the function `func` in [Exercise 6.4](# Exercise-64) shouldn't. It is not that small and it's only being called once. Hence, it will probably not expand as inline.\n\n## Exercise 6.46\n> Would it be possible to define `isShorter` as a `constexpr`? If so, do so. If not, explain why not.\n\nNo.\n\nBecause `std::string::size()` is not a `constexpr` function and `s1.size() == s2.size()` is not a constant expression.\n\n> **For a** non-template, non-defaulted **constexpr function** or a non-template, non-defaulted, non-inheriting\nconstexpr constructor, **if no argument values exist such that an invocation of the function or constructor\ncould be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed;** no\ndiagnostic required. (N3690 §7.1.5 [dcl.constexpr]/5)\n\n## [Exercise 6.47](ex6_47.cpp)\n## Exercise 6.48\n\nThis loop let user input a word all the way until the word is sought.\n\nIt isn't a good use of assert. because if user begin to input a word, the `cin` would be always have content. so the `assert` would be always `true`. It is meaningless. using `assert(s == sought)` is better.\n\n## Exercise 6.49\n\ncandidate function:\n>Set of functions that are considered when resolving a function call. (all the functions\nwith the name used in the call for which a declaration is in scope at the time of the call.)\n\nviable function:\n>Subset of the candidate functions that could match a given call.\n>It have the same number of parameters as arguments to the call,\nand each argument type can be converted to the corresponding parameter type.\n\n## Exercise 6.50\n\n(a) illegal. 2.56 match the `double`, but 42 match the `int`.\n\n(b) match `void f(int)`.\n\n(c) match `void f(int, int)`.\n\n(d) match `void f(double, double = 3.14)`.\n\n## [Exercise 6.51](ex6_51.cpp)\n## Exercise 6.52\n\n(a) Match through a promotion\n\n(b) Arithmetic type conversion\n\n## Exercise 6.53\n\n(a)\n```cpp\nint calc(int&, int&); // calls lookup(int&)\nint calc(const int&, const int&); // calls lookup(const int&)\n```\n(b)\n```cpp\nint calc(char*, char*); // calls lookup(char*)\nint calc(const char*, const char*); // calls lookup(const char *)\n```\n(c)\n\nillegal. both calls lookup(char*)\n\n## Exercise 6.54\n```cpp\nint func(int a, int b);\n\nusing pFunc1 = decltype(func) *;\ntypedef decltype(func) *pFunc2;\nusing pFunc3 = int (*)(int a, int b);\nusing pFunc4 = int(int a, int b);\ntypedef int(*pFunc5)(int a, int b);\nusing pFunc6 = decltype(func);\n\nstd::vector<pFunc1> vec1;\nstd::vector<pFunc2> vec2;\nstd::vector<pFunc3> vec3;\nstd::vector<pFunc4*> vec4;\nstd::vector<pFunc5> vec5;\nstd::vector<pFunc6*> vec6;\n```\n\n## Exercise 6.55\n```cpp\nint add(int a, int b) { return a + b; }\nint subtract(int a, int b) { return a - b; }\nint multiply(int a, int b) { return a * b; }\nint divide(int a, int b) { return b != 0 ? a / b : 0; }\n\nvec1.push_back(add);\nvec1.push_back(subtract);\nvec1.push_back(multiply);\nvec1.push_back(divide);\n```\n\n## Exercise 6.56\n```cpp\nstd::vector<decltype(func) *> vec{ add, subtract, multiply, divide };\nfor (auto f : vec)\n          std::cout << f(2, 2) << std::endl;\n```\n\n----\n\nsee @Mooophy 's [complete codes](ex6_54_55_56.cpp).\n"
  },
  {
    "path": "ch06/ex6_10.cpp",
    "content": "//@Yue wang\n//\n// Exercise 6.10:\n// Using pointers, write a function to swap the values of two ints.\n// Test the function by calling it and printing the swapped values.\n//\n#include <iostream>\n#include <string>\n#include <stdexcept>\n\n\nvoid swap(int* lhs, int* rhs)\n{\n    int tmp;\n    tmp = *lhs;\n    *lhs = *rhs;\n    *rhs = tmp;\n}\n\nint main()\n{\n    for (int lft, rht; std::cout << \"Please Enter:\\n\", std::cin >> lft >> rht; )\n    {\n        swap(&lft, &rht);\n        std::cout << lft << \" \" << rht << std::endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_11.cpp",
    "content": "#include <iostream>\n\nvoid reset(int &i)\n{\n    i = 0;\n}\n\nint main()\n{\n    int i = 42;\n    reset(i);\n    std::cout << i  << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_12.cpp",
    "content": "//@Yue Wang\n//\n// Exercise 6.12:\n// Rewrite the program from exercise 6.10 in § 6.2.1 (p. 210) to use\n// references instead of pointers to swap the value of two ints. Which\n// version do you think would be easier to use and why?\n//  The version using reference is easier.\n//\n#include <iostream>\n#include <string>\n\n\nvoid swap(int& lhs, int& rhs)\n{\n    int temp = lhs;\n    lhs = rhs;\n    rhs = temp;\n}\n\nint main()\n{\n    for (int left, right; std::cout << \"Please Enter:\\n\", std::cin >> left >> right; )\n    {\n        swap(left, right);\n        std::cout << left << \" \" << right << std::endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_17.cpp",
    "content": "#include <iostream>\n#include <string>\nusing std::cout; using std::endl; using std::string;\n\nbool any_capital(string const& str)\n{\n    for (auto ch : str)\n        if (isupper(ch)) return true;\n    return false;\n}\n\nvoid to_lowercase(string& str)\n{\n    for (auto& ch : str) ch = tolower(ch);\n}\n\nint main()\n{\n    string hello(\"Hello World!\");\n    cout << any_capital(hello) << endl;\n\n    to_lowercase(hello);\n    cout << hello << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_21.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 6.21:\n// Write a function that takes an int and a pointer to an int and\n// returns the larger of the int value or the value to which the\n// pointer points. What type should you use for the pointer?\n//\n\n#include <iostream>\nusing std::cout;\n\nint larger_one(const int i, const int *const p)\n{\n    return (i > *p) ? i : *p;\n}\n\nint main()\n{\n    int i = 6;\n    cout << larger_one(7, &i);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_22.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 6.22:\n// Write a function to swap two int pointers.\n//\n#include <iostream>\n#include <string>\n\nvoid swap(int*& lft, int*& rht)\n{\n    auto tmp = lft;\n    lft = rht;\n    rht = tmp;\n}\n\nint main()\n{\n    int i = 42, j = 99;\n    auto lft = &i;\n    auto rht = &j;\n    swap(lft, rht);\n    std::cout << *lft << \" \" << *rht << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_23.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::endl; using std::begin; using std::end;\n\nvoid print(const int *pi)\n{\n    if(pi)\n        cout << *pi << endl;\n}\n\nvoid print(const char *p)\n{\n    if (p)\n        while (*p) cout << *p++;\n    cout << endl;\n}\n\nvoid print(const int *beg, const int *end)\n{\n    while (beg != end)\n        cout << *beg++ << endl;\n}\n\nvoid print(const int ia[], size_t size)\n{\n    for (size_t i = 0; i != size; ++i) {\n        cout << ia[i] << endl;\n    }\n}\n\nvoid print(int (&arr)[2])\n{\n    for (auto i : arr)\n        cout << i << endl;\n}\n\nint main()\n{\n    int i = 0, j[2] = { 0, 1 };\n    char ch[5] = \"pezy\";\n    \n    print(ch);\n    print(begin(j), end(j));\n    print(&i);\n    print(j, end(j)-begin(j));\n    print(j);\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_25_26.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 6.25: Write a main function that takes two arguments.\n// Concatenate the supplied arguments and print the resulting string.\n//\n// Exercise 6.26: Write a program that accepts the options presented\n// in this section. Print the values of the arguments passed to main.\n//\n\n#include <iostream>\n#include <string>\n\nint main(int argc, char **argv)\n{\n    std::string str;\n    for (int i = 1; i != argc; ++i)\n        str += std::string(argv[i]) + \" \";\n\n    std::cout << str << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_27.cpp",
    "content": "#include <iostream>\n#include <initializer_list>\n\nint sum(std::initializer_list<int> const& il)\n{\n    int sum = 0;\n    for (auto i : il) sum += i;\n    return sum;\n}\n\nint main(void)\n{\n    auto il = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    std::cout << sum(il) << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_33.cpp",
    "content": "#include <iostream>\n#include <vector>\nusing std::vector; using std::cout;\nusing Iter = vector<int>::const_iterator;\n\nvoid print(Iter first, Iter last)\n{\n    if (first != last)\n    {\n        cout << *first << \" \";\n        print(++first, last);\n    }\n}\n\nint main()\n{\n    vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    print(vec.cbegin(), vec.cend());\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_42.cpp",
    "content": "// @creator by Wang Yue\n// @refactor by pezy\n//\n// @date 27, July. 2015\n//\n// @question\n// Give the second parameter of make_plural (§ 6.3.2, p. 224) a default\n// argument of 's'. Test your program by printing singular and plural versions\n// of the words success and failure.\n//\n\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cout;\nusing std::endl;\n\nstring make_plural(size_t ctr, const string& word, const string& ending = \"s\")\n{\n    return (ctr > 1) ? word + ending : word;\n}\n\nint main()\n{\n    cout << \"singual: \" << make_plural(1, \"success\", \"es\") << \" \"\n         << make_plural(1, \"failure\") << endl;\n    cout << \"plural : \" << make_plural(2, \"success\", \"es\") << \" \"\n         << make_plural(2, \"failure\") << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_44.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 6.44: Rewrite the isShorter function from § 6.2.2 (p. 211) to be inline.\n//\n#include <iostream>\n#include <string>\nusing std::string; using std::cout; using std::endl;\n\ninline bool is_shorter(const string &lft, const string &rht) // defining in the header is better.\n{\n    return lft.size() < rht.size();\n}\n\nint main()\n{\n    cout << is_shorter(\"pezy\", \"mooophy\") << endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_47.cpp",
    "content": "//\n//  main.cpp\n//  Test\n//\n//  Created by pezy on 14/10/30.\n//\n// To turn off debugging, uncomment the following line, or compile the program with '-D NDEBUG' switch\n//#define NDEBUG \n\n#include <iostream>\n#include <vector>\nusing std::vector; using std::cout; using std::endl;\n\nvoid printVec(vector<int> &vec)\n{\n#ifndef NDEBUG\n    cout << \"vector size: \" << vec.size() << endl;\n#endif\n    if (!vec.empty())\n    {\n        auto tmp = vec.back();\n        vec.pop_back();\n        printVec(vec);\n        cout << tmp << \" \";\n    }\n}\n\nint main()\n{\n    vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    printVec(vec);\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_51.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::endl;\n\nvoid f()\n{\n    cout << \"f()\" << endl;\n}\n\nvoid f(int)\n{\n    cout << \"f(int)\" << endl;\n}\n\nvoid f(int, int)\n{\n    cout << \"f(int, int)\" << endl;\n}\n\nvoid f(double, double)\n{\n    cout << \"f(double, double)\" << endl;\n}\n\nint main()\n{\n    //f(2.56, 42); // error: 'f' is ambiguous.\n    f(42);\n    f(42, 0);\n    f(2.56, 3.14);\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch06/ex6_54_55_56.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 6.54:\n// Write a declaration for a function that takes two int\n// parameters and returns an int, and declare a vector whose\n// elements have this function pointer type.\n//\n// Exercise 6.55:\n// Write four functions that add, subtract, multiply, and divide\n// two int values. Store pointers to these functions in your\n// vector from the previous exercise.\n//\n// Exercise 6.56:\n// Call each element in the vector and print their result.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\nusing std::vector; using std::cout;\n\n//\n// @brief Exercise 6.54\n// @note  define the function type fp\n//\ninline int f(const int, const int);\ntypedef decltype(f) fp;//fp is just a function type not a function pointer\n\n//\n// @brief Exercise 6.55\n// @note  Store pointers to these functions in the vector\n//\ninline int NumAdd(const int n1, const int n2)  { return n1 + n2; }\ninline int NumSub(const int n1, const int n2)  { return n1 - n2; }\ninline int NumMul(const int n1, const int n2)  { return n1 * n2; }\ninline int NumDiv(const int n1, const int n2)  { return n1 / n2; }\n\nvector<fp*> v{ NumAdd, NumSub, NumMul, NumDiv };\n\nint main()\n{\n    //\n    // @brief Exercise 6.56\n    // @note  Call each element in the vector and print their result.\n    //\n    for (auto it = v.cbegin(); it != v.cend(); ++it)\n        cout << (*it)(2, 2) << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch06/fact.cc",
    "content": "#include \"Chapter6.h\"\n#include <iostream>\n\nint fact(int val)\n{\n    if (val == 0 || val == 1) return 1;\n    else return val * fact(val-1);\n}\n\nint func()\n{\n    int n, ret = 1;\n    std::cout << \"input a number: \";\n    std::cin >> n;\n    while (n > 1) ret *= n--;\n    return ret;\n}\n"
  },
  {
    "path": "ch06/factMain.cc",
    "content": "#include \"Chapter6.h\"\n#include <iostream>\n\nint main()\n{\n    std::cout << \"5! is \" << fact(5) << std::endl; \n    std::cout << func() << std::endl; \n    std::cout << abs(-9.78) << std::endl;\n}\n"
  },
  {
    "path": "ch07/README.md",
    "content": "## [Exercise 7.1](ex7_01.cpp)\n## [Exercise 7.2](ex7_02.h)\n## [Exercise 7.3](ex7_03.cpp)\n## [Exercise 7.4](ex7_04.h)\n## [Exercise 7.5](ex7_05.h)\n## [Exercise 7.6](ex7_06.h)\n## [Exercise 7.7](ex7_07.cpp)\n## Exercise 7.8\n\nDefine `read`'s Sales_data parameter as plain reference since it's intended to change the `revenue`'s value.\n\nDefine `print`'s Sales_data parameter as a reference to const since it isn't intended to change any member's value of this object.\n\n## [Exercise 7.9](ex7_09.h)\n## Exercise 7.10\n\n```cpp\nif(read(read(cin, data1), data2))\n```\n\nwe can try to divide it like that:\n```\nstd::istream &firstStep = read(cin, data1);\nsdt::istream &secondStep = read(firstStep, data2);\nif (secondStep)\n```\nthe condition of the `if` statement would read two Sales_data object at one time.\n\n## Exercise 7.11 [Header](ex7_11.h)|[CPP](ex7_11.cpp)\n## [Exercise 7.12](ex7_12.h)\n## [Exercise 7.13](ex7_13.cpp)\n## Exercise 7.14\n```cpp\nSales_data() : bookNo(\"\"), units_sold(0) , revenue(0){ }\n```\n\n## [Exercise 7.15](ex7_15.h)\n\n## Exercise 7.16\n\nThere are no restrictions on how often an access specifier may appear.The specified\naccess level remains in effect until the next access specifier or the end of the class body.\n\nThe members which are accessible to all parts of the program should define after a public specifier.\n\nThe members which are accessible to the member functions of the class but are not accessible to code that uses the class should define after a private specifier.\n\n## Exercise 7.17\n\nThe only difference between using `class` and using `struct` to define a class is the default access level. (`class` : private, `struct` : public)\n\n## Exercise 7.18\n\nencapsulation is the separation of implementation from interface. It hides the implementation details of a type. (In C++, encapsulation is enforced by putting the implementation in the private part of a class)\n\n-----\n\nImportant advantages:\n\n- User code cannot inadvertently corrupt the state of an encapsulation object.\n- The implementation of an encapsulated class can change over time without requiring changes in user-level code.\n\n## Exercise 7.19\n\npublic include: constructors, `getName()`, `getAddress()`.\nprivate include: `name`, `address`.\n\nthe interface should be defined as public, the data shouldn't expose to outside of the class.\n\n## Exercise 7.20\n\n`friend` is a mechanism by which a class grants access to its nonpublic members. They have the same rights as members.\n\n**Pros**:\n- the useful functions can refer to class members in the class scope without needing to explicitly prefix them with the class name.\n- you can access all the nonpublic members conveniently.\n- sometimes, more readable to the users of class.\n\n**Cons**:\n- lessens encapsulation and therefore maintainability.\n- code verbosity, declarations inside the class, outside the class.\n\n## [Exercise 7.21](ex7_21.h)\n## [Exercise 7.22](ex7_22.h)\n## [Exercise 7.23](ex7_23.h)\n## [Exercise 7.24](ex7_24.h)\n\n## Exercise 7.25\n\nThe class below can rely on it. It goes in *Section 7.1.5*:\n>..the synthesized versions are unlikely to work correctly for classes that allocate resources that reside outside the class objects themselves.\n\n>Moreover, the synthesized versions for copy, assignment, and destruction work correctly for classes that have **vector or string members**.\n\nHence the class below which used only built-in type and strings can rely on the default version of copy and assignment. (by @Mooophy)\n\n## Exercise 7.26 [Header](ex7_26.h)|[CPP](ex7_26.cpp)\n## Exercise 7.27 [Class](ex7_27.h)|[Test](ex7_27_TEST.cpp)\n\n## Exercise 7.28\n\nThe second call to `display` couldn't print `#` among the output, cause the call to `set` would change the **temporary copy**, not myScreen.\n\n## Exercise 7.29\n\n```sh\n#with '&'\nXXXXXXXXXXXXXXXXXXXX#XXXX\nXXXXXXXXXXXXXXXXXXXX#XXXX\n                   ^^^\n# without '&'\nXXXXXXXXXXXXXXXXXXXX#XXXX\nXXXXXXXXXXXXXXXXXXXXXXXXX\n                   ^^^\n```\n\n## Exercise 7.30\n\n**Pros**\n\n- more explicit\n- less scope for misreading\n- can use the member function parameter which name is same as the member name.\n\n        void setAddr(const std::string &addr) { this->addr = addr; }\n\n**Cons**\n\n- more to read\n- sometimes redundant\n\n        std::string getAddr() const { return this->addr; } // unnecessary\n\n## [Exercise 7.31](ex7_31.h)\n## [Exercise 7.32](ex7_32.h)\n## Exercise 7.33\n\n[clang]error: unknown type name 'pos'\n\nfixed:\n```cpp\nScreen::pos Screen::size() const\n{\n    return height*width;\n}\n```\n\n## Exercise 7.34\n\nThere is an error in\n\n    dummy_fcn(pos height)\n               ^\n    Unknown type name 'pos'\n\n## Exercise 7.35\n\n```cpp\ntypedef string Type;\nType initVal(); // use `string`\nclass Exercise {\npublic:\n    typedef double Type;\n    Type setVal(Type); // use `double`\n    Type initVal(); // use `double`\nprivate:\n    int val;\n};\n\nType Exercise::setVal(Type parm) {  // first is `string`, second is `double`\n    val = parm + initVal();     // Exercise::initVal()\n    return val;\n}\n```\n\n**fixed**\n\nchanged\n\n```cpp\nType Exercise::setVal(Type parm) {\n    val = parm + initVal();\n    return val;\n}\n```\nto\n```cpp\nExercise::Type Exercise::setVal(Type parm) {\n    val = parm + initVal();\n    return val;\n}\n```\n\nand `Exercise::initVal()` should be defined.\n\n## Exercise 7.36\n\n>In this case, the constructor initializer makes it appear as if `base` is initialized with `i` and then `base` is used to initialize `rem`. However, `rem` is initialized first. The effect of this initializer is to initialize `rem` with the undefined value of `base`!\n\n**fixed**\n```cpp\nstruct X {\n  X (int i, int j): base(i), rem(i % j) { }\n  int base, rem;\n};\n```\n\n## Exercise 7.37\n\n```cpp\nSales_data first_item(cin);   // use Sales_data(std::istream &is) ; its value are up to your input.\n\nint main() {\n  Sales_data next;  // use Sales_data(std::string s = \"\"); bookNo = \"\", cnt = 0, revenue = 0.0\n  Sales_data last(\"9-999-99999-9\"); // use Sales_data(std::string s = \"\"); bookNo = \"9-999-99999-9\", cnt = 0, revenue = 0.0\n}\n```\n\n## Exercise 7.38\n\n```cpp\nSales_data(std::istream &is = std::cin) { read(is, *this); }\n```\n\n## Exercise 7.39\n\nillegal. cause the call of overloaded 'Sales_data()' is **ambiguous**.\n\n## Exercise 7.40\n```cpp\n#include <iostream>\n#include <string>\n\nclass Book \n{\npublic:\n    Book(unsigned isbn, std::string const& name, std::string const& author, std::string const& pubdate)\n        :isbn_(isbn), name_(name), author_(author), pubdate_(pubdate)\n    { }\n\n    explicit Book(std::istream &in) \n    { \n        in >> isbn_ >> name_ >> author_ >> pubdate_;\n    }\n\nprivate:\n    unsigned isbn_;\n    std::string name_;\n    std::string author_;\n    std::string pubdate_;\n};\n```\n\n## Exercise 7.41 [Header](ex7_41.h)|[Cpp](ex7_41.cpp)|[Test](ex7_41_TEST.cpp)\n## Exercise 7.42\n\n```cpp\n#include <iostream>\n#include <string>\n\nclass Book \n{\npublic:\n    Book(unsigned isbn, std::string const& name, std::string const& author, std::string const& pubdate)\n        :isbn_(isbn), name_(name), author_(author), pubdate_(pubdate)\n    { }\n\n    explicit Book(std::istream &in) \n    { \n        in >> isbn_ >> name_ >> author_ >> pubdate_;\n    }\n\nprivate:\n    unsigned isbn_;\n    std::string name_;\n    std::string author_;\n    std::string pubdate_;\n};\n```\n\n## [Exercise 7.43](ex7_43.cpp)\n## Exercise 7.44\n\nillegal, cause there are ten elements, each would be default initialized. But no default initializer for the temporary object.\n\n## Exercise 7.45\n\nNo problem. cause `C` have the default constructor.\n\n## Exercise 7.46\n\n- a) A class must provide at least one constructor. (**untrue**, \"The compiler-generated constructor is known as the synthesized default constructor.\")\n- b) A default constructor is a constructor with an empty parameter list. (**untrue**,  A default constructor is a constructor that is used if no initializer is supplied.What's more, A constructor that supplies default arguments for all its parameters also defines the default constructor)\n- c) If there are no meaningful default values for a class, the class should not provide a default constructor. (**untrue**, the class should provide.)\n- d) If a class does not define a default constructor, the compiler generates one that initializes each data member to the default value of its associated type. (**untrue**, only if our class does not explicitly define **any constructors**, the compiler will implicitly define the default constructor for us.)\n\n## Exercise 7.47\n\nWhether the conversion of a `string` to `Sales_data` is desired **depends on how we think our users will use the conversion**. In this case, it might be okay. The `string` in null_book probably represents a nonexistent ISBN.\n\nBenefits:\n\n- prevent the use of a constructor in a context that requires an implicit conversion\n- we can define a constructor which is used only with the direct form of initialization\n\nDrawbacks:\n\n- meaningful only on constructors that can be called with a single argument\n\n## Exercise 7.48\n\nBoth are nothing happened.\n\n## Exercise 7.49\n\n```cpp\n(a) Sales_data &combine(Sales_data); // ok\n(b) Sales_data &combine(Sales_data&); // [Error] no matching function for call to 'Sales_data::combine(std::string&)' (`std::string&` can not convert to `Sales_data` type.)  \n(c) Sales_data &combine(const Sales_data&) const; // The trailing const mark can't be put here, as it forbids any mutation on data members. This conflicts with combine's semantics.\n```\nSome detailed explanation about problem (b) :It's wrong. Because `combine`’s parameter is  a non-const reference , we can't  pass a temporary to that parameter. If `combine`’s parameter is  a  reference to const , we can  pass a temporary to that parameter. Like this :`Sales_data &combine(const Sales_data&); `  Here we call the `Sales_data` `combine` member function with a string argument. This call is perfectly legal; the compiler automatically creates a `Sales_data` object from the given string. That newly generated (temporary) `Sales_data` is passed to `combine`.(Also you can read C++ Primer Page 295(English Edition))\n\n## [Exercise 7.50](ex7_50.h)\n## Exercise 7.51\n\nSuch as a function like that:\n\n```cpp\nint getSize(const std::vector<int>&);\n```\n\nif vector has not defined its single-argument constructor as explicit. we can use the function like:\n\n```cpp\ngetSize(34);\n```\n\nWhat is this mean? It's very confused.\n\nBut the `std::string` is different. In ordinary, we use `std::string` to replace `const char *`(the C language). so when we call a function like that:\n\n```cpp\nvoid setYourName(std::string); // declaration.\nsetYourName(\"pezy\"); // just fine.\n```\n\nit is very natural.\n\n## Exercise 7.52\n\nIn my opinion , the aim of the problem is Aggregate Class. Test-makers think that `Sales_data` is Aggregate Class, so `Sales_data` should have no in-class initializers if we want to initialize the data members of an aggregate class by providing a braced list of member initializers:\n\nFIXED:\n\n```cpp\nstruct Sales_data {\n    std::string bookNo;\n    unsigned units_sold;\n    double revenue;\n};\n```\n\n## [Exercise 7.53](ex7_53.h)\n\n## Exercise 7.54\n\nin C++11, constexpr member functions are implicitly const, so the \"set_xx\" functions, which will modify data members, cannot be declared as constexpr. In C++14, this property no longer holds, so constexpr is suitable.\n\n## Exercise 7.55\n\nno.\n\n`std::string` is not a literal type, and it can be verified by following codes:\n\n```cpp\n#include <string>\n#include <iostream>\n#include <type_traits>\n\nstruct Data {\n    int ival;\n    std::string s;\n};\n\nint main()\n{\n    std::cout << std::boolalpha;\n    std::cout << std::is_literal_type<Data>::value << std::endl;\n    // output: false\n}\n```\n\n## Exercise 7.56\n\n>What is a static class member?\n\nA class member that is **associated with the class**, rather than with individual objects of the class type.\n\n>What are the advantages of static members?\n\neach object can no need to store a common data. And if the data is changed, each object can use the new value.\n\n>How do they differ from ordinary members?\n\n- a static data member can have **incomplete type**.\n- we can use a static member **as a default argument**.\n\n## [Exercise 7.57](ex7_57.h)\n\n## Exercise 7.58\n\n```cpp\nstatic double rate = 6.5;\n                ^\n            rate should be a constant expression.\n\nstatic vector<double> vec(vecSize);\n                            ^\n            we may not specify an in-class initializer inside parentheses.\n```\n\nFixed:\n\n```cpp\n// example.h\nclass Example {\npublic:\n    static constexpr double rate = 6.5;\n    static const int vecSize = 20;\n    static vector<double> vec;\n};\n\n// example.C\n#include \"example.h\"\nconstexpr double Example::rate;\nvector<double> Example::vec(Example::vecSize);\n```\n"
  },
  {
    "path": "ch07/ex7_01.cpp",
    "content": "//\n//  ex7_01.cpp\n//  Exercise 7.1\n//\n//  Created by pezy on 14/10/30.\n//\n#include <iostream>\n#include <string>\nusing std::cin; using std::cout; using std::endl; using std::string;\n\nstruct Sales_data\n{\n    string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nint main()\n{\n    Sales_data total;\n    if (cin >> total.bookNo >> total.units_sold >> total.revenue)\n    {\n        Sales_data trans;\n        while (cin >> trans.bookNo >> trans.units_sold >> trans.revenue) \n        {\n            if (total.bookNo == trans.bookNo) \n            {\n                total.units_sold += trans.units_sold;\n                total.revenue += trans.revenue;\n            }\n            else\n            {\n                cout << total.bookNo << \" \" << total.units_sold << \" \" << total.revenue << endl;\n                total = trans;\n            }\n        }\n        cout << total.bookNo << \" \" << total.units_sold << \" \" << total.revenue << endl;\n    }\n    else\n    {\n        std::cerr << \"No data?!\" << std::endl;\n        return -1;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_02.h",
    "content": "//\n//  ex7_02.h\n//  Exercise 7.2\n//\n//  Created by pezy on 14/11/8.\n//\n\n#ifndef CP5_ex7_02_h\n#define CP5_ex7_02_h\n\n#include <string>\n\nstruct Sales_data {\n    std::string isbn() const { return bookNo; };\n    Sales_data& combine(const Sales_data&);\n    \n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nSales_data& Sales_data::combine(const Sales_data& rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_03.cpp",
    "content": "//\n//  ex7_03.cpp\n//  Exercise 7.03\n//\n//  Created by pezy on 14/11/8.\n//\n\n#include \"ex7_02.h\"\n#include <iostream>\nusing std::cin; using std::cout; using std::endl;\n\nint main()\n{\n    Sales_data total;\n    if (cin >> total.bookNo >> total.units_sold >> total.revenue)\n    {\n        Sales_data trans;\n        while (cin >> trans.bookNo >> trans.units_sold >> trans.revenue) {\n            if (total.isbn() == trans.isbn())\n                total.combine(trans);\n            else {\n                cout << total.bookNo << \" \" << total.units_sold << \" \" << total.revenue << endl;\n                total = trans;\n            }\n        }\n        cout << total.bookNo << \" \" << total.units_sold << \" \" << total.revenue << endl;\n    }\n    else\n    {\n        std::cerr << \"No data?!\" << std::endl;\n        return -1;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_04.h",
    "content": "//\n//  ex7_04.h\n//  Exercise 7.4\n//\n//  Created by pezy on 14/11/8.\n//\n\n#ifndef CP5_ex7_04_h\n#define CP5_ex7_04_h\n\n#include <string>\n\nclass Person {\n    std::string name;\n    std::string address;\n};\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_05.h",
    "content": "//\n//  ex7_05.h\n//  Exercise 7.5\n//\n//  Created by pezy on 14/11/8.\n//\n//  Revised by @Yue Wang Jun 2015:\n//\n//  1. add public access modifier for the function members\n//  2. use trailing return type \n//  3. change return type from string to string const&, for better performance.\n//\n\n#ifndef CP5_ex7_05_h\n#define CP5_ex7_05_h\n\n#include <string>\n\nclass Person \n{\n    std::string name;\n    std::string address;\npublic:\n    auto get_name() const -> std::string const& { return name; }\n    auto get_addr() const -> std::string const& { return address; }\n};\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_06.h",
    "content": "//\n//  ex7_06.h\n//  Exercise 7.6\n//\n//  Created by pezy on 11/8/14.\n//\n\n#ifndef CP5_ex7_06_h\n#define CP5_ex7_06_h\n\n#include <string>\n#include <iostream>\n\nstruct Sales_data {\n    std::string const& isbn() const { return bookNo; };\n    Sales_data& combine(const Sales_data&);\n\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\n// member functions.\nSales_data& Sales_data::combine(const Sales_data& rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n// nonmember functions\nstd::istream &read(std::istream &is, Sales_data &item)\n{\n    double price = 0;\n    is >> item.bookNo >> item.units_sold >> price;\n    item.revenue = price * item.units_sold;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue;\n    return os;\n}\n\nSales_data add(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum.combine(rhs);\n    return sum;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_07.cpp",
    "content": "//\n//  ex7_07.cpp\n//  Exercise 7.7\n//\n//  Created by pezy on 11/8/14.\n//\n\n#include \"ex7_06.h\"\n\nint main()\n{\n    Sales_data total;\n    if (read(std::cin, total))\n    {\n        Sales_data trans;\n        while (read(std::cin, trans)) {\n            if (total.isbn() == trans.isbn())\n                total.combine(trans);\n            else {\n                print(std::cout, total) << std::endl;\n                total = trans;\n            }\n        }\n        print(std::cout, total) << std::endl;\n    }\n    else\n    {\n        std::cerr << \"No data?!\" << std::endl;\n        return -1;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_09.h",
    "content": "//\n//  ex7_09.h\n//  Exercise 7.9\n//\n//  Created by pezy on 11/8/14.\n//\n//\n//  Revied by @Yue Wang Jun 2015\n//\n\n#ifndef CP5_ex7_09_h\n#define CP5_ex7_09_h\n\n#include <string>\n#include <iostream>\n\nstruct Person \n{\n    std::string const& getName()    const { return name; }\n    std::string const& getAddress() const { return address; }\n    \n    std::string name;\n    std::string address;\n};\n\nstd::istream &read(std::istream &is, Person &person)\n{\n    return is >> person.name >> person.address;\n}\n\nstd::ostream &print(std::ostream &os, const Person &person)\n{\n    return os << person.name << \" \" << person.address;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_11.cpp",
    "content": "//\n//  ex7_11.cpp\n//  Exercise 7.11\n//\n//  Created by pezy on 11/9/14.\n//\n\n#include \"ex7_11.h\"\n\nint main()\n{\n    Sales_data item1;\n    print(std::cout, item1) << std::endl;\n    \n    Sales_data item2(\"0-201-78345-X\");\n    print(std::cout, item2) << std::endl;\n    \n    Sales_data item3(\"0-201-78345-X\", 3, 20.00);\n    print(std::cout, item3) << std::endl;\n    \n    Sales_data item4(std::cin);\n    print(std::cout, item4) << std::endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_11.h",
    "content": "//\n//  ex7_11.h\n//  Exercise 7.11\n//\n//  Created by pezy on 11/9/14.\n//\n\n#ifndef CP5_ex7_11_h\n#define CP5_ex7_11_h\n\n#include <string>\n#include <iostream>\n\nstruct Sales_data {\n    Sales_data() = default;\n    Sales_data(const std::string &s):bookNo(s) { }\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data(std::istream &is);\n    \n    std::string isbn() const { return bookNo; };\n    Sales_data& combine(const Sales_data&);\n    \n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\n// nonmember functions\nstd::istream &read(std::istream &is, Sales_data &item)\n{\n    double price = 0;\n    is >> item.bookNo >> item.units_sold >> price;\n    item.revenue = price * item.units_sold;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue;\n    return os;\n}\n\nSales_data add(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum.combine(rhs);\n    return sum;\n}\n\n// member functions.\nSales_data::Sales_data(std::istream &is)\n{\n    read(is, *this);\n}\n\nSales_data& Sales_data::combine(const Sales_data& rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_12.h",
    "content": "//\n//  ex7_12.h\n//  Exercise 7.12\n//\n//  Created by pezy on 11/9/14.\n//\n\n#ifndef CP5_ex7_12_h\n#define CP5_ex7_12_h\n\n#include <string>\n#include <iostream>\n\nstruct Sales_data;\nstd::istream &read(std::istream&, Sales_data&);\n\nstruct Sales_data {\n    Sales_data() = default;\n    Sales_data(const std::string &s):bookNo(s) { }\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data(std::istream &is) { read(is, *this); }\n    \n    std::string isbn() const { return bookNo; };\n    Sales_data& combine(const Sales_data&);\n    \n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\n// member functions.\nSales_data& Sales_data::combine(const Sales_data& rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n// nonmember functions\nstd::istream &read(std::istream &is, Sales_data &item)\n{\n    double price = 0;\n    is >> item.bookNo >> item.units_sold >> price;\n    item.revenue = price * item.units_sold;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue;\n    return os;\n}\n\nSales_data add(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum.combine(rhs);\n    return sum;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_13.cpp",
    "content": "//\n//  ex7_13.cpp\n//  Exercise 7.13\n//\n//  Created by pezy on 11/9/14.\n//\n\n#include \"ex7_12.h\"\n\nint main()\n{\n    Sales_data total(std::cin);\n    if (!total.isbn().empty())\n    {\n        std::istream &is = std::cin;\n        while (is) {\n            Sales_data trans(is);\n            if (!is) break;\n            if (total.isbn() == trans.isbn())\n                total.combine(trans);\n            else {\n                print(std::cout, total) << std::endl;\n                total = trans;\n            }\n        }\n        print(std::cout, total) << std::endl;\n    }\n    else\n    {\n        std::cerr << \"No data?!\" << std::endl;\n        return -1;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_15.h",
    "content": "//\n//  ex7_15.h\n//  Exercise 7.15\n//\n//  Created by pezy on 11/9/14.\n//\n\n#ifndef CP5_ex7_15_h\n#define CP5_ex7_15_h\n\n#include <string>\n#include <iostream>\n\nstruct Person;\nstd::istream &read(std::istream&, Person&);\n\nstruct Person {\n    Person() = default;\n    Person(const std::string sname, const std::string saddr):name(sname), address(saddr){ }\n    Person(std::istream &is){ read(is, *this); }\n    \n    std::string getName() const { return name; }\n    std::string getAddress() const { return address; }\n    \n    std::string name;\n    std::string address;\n};\n\nstd::istream &read(std::istream &is, Person &person)\n{\n    is >> person.name >> person.address;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Person &person)\n{\n    os << person.name << \" \" << person.address;\n    return os;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_21.h",
    "content": "//\n//  ex7_21.h\n//  Exercise 7.21\n//\n//  Created by pezy on 11/13/14.\n//\n\n#ifndef CP5_ex7_21_h\n#define CP5_ex7_21_h\n\n#include <string>\n#include <iostream>\n\nclass Sales_data {\n    friend std::istream &read(std::istream &is, Sales_data &item);\n    friend std::ostream &print(std::ostream &os, const Sales_data &item);\n    friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs);\n\npublic:\n    Sales_data() = default;\n    Sales_data(const std::string &s):bookNo(s) { }\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data(std::istream &is) { read(is, *this); }\n\n    std::string isbn() const { return bookNo; };\n    Sales_data& combine(const Sales_data&);\n\nprivate:\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\n// member functions.\nSales_data& Sales_data::combine(const Sales_data& rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n// friend functions\nstd::istream &read(std::istream &is, Sales_data &item)\n{\n    double price = 0;\n    is >> item.bookNo >> item.units_sold >> price;\n    item.revenue = price * item.units_sold;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue;\n    return os;\n}\n\nSales_data add(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum.combine(rhs);\n    return sum;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_22.h",
    "content": "//\n//  ex7_22.h\n//  Exercise 7.22\n//\n//  Created by pezy on 11/13/14.\n//\n\n#ifndef CP5_ex7_22_h\n#define CP5_ex7_22_h\n\n#include <string>\n#include <iostream>\n\nclass Person {\n    friend std::istream &read(std::istream &is, Person &person);\n    friend std::ostream &print(std::ostream &os, const Person &person);\n\npublic:\n    Person() = default;\n    Person(const std::string sname, const std::string saddr):name(sname), address(saddr){ }\n    Person(std::istream &is){ read(is, *this); }\n\n    std::string getName() const { return name; }\n    std::string getAddress() const { return address; }\nprivate:\n    std::string name;\n    std::string address;\n};\n\nstd::istream &read(std::istream &is, Person &person)\n{\n    is >> person.name >> person.address;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Person &person)\n{\n    os << person.name << \" \" << person.address;\n    return os;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_23.h",
    "content": "//\n//  ex7_23.h\n//  Exercise 7.23\n//\n//  Created by pezy on 11/14/14.\n//\n\n#ifndef CP5_ex7_23_h\n#define CP5_ex7_23_h\n\n#include <string>\n\nclass Screen {\n    public:\n        using pos = std::string::size_type;\n\n        Screen() = default;\n        Screen(pos ht, pos wd, char c):height(ht), width(wd), contents(ht*wd, c){ }\n\n        char get() const { return contents[cursor]; }\n        char get(pos r, pos c) const { return contents[r*width+c]; }\n\n    private:\n        pos cursor = 0;\n        pos height = 0, width = 0;\n        std::string contents;\n};\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_24.h",
    "content": "//\n//  ex7_24.cpp\n//  Exercise 7.24\n//\n//  Created by pezy on 11/14/14.\n//\n\n#ifndef CP5_ex7_24_h\n#define CP5_ex7_24_h\n\n#include <string>\n\nclass Screen {\n    public:\n        using pos = std::string::size_type;\n\n        Screen() = default; // 1\n        Screen(pos ht, pos wd):height(ht), width(wd), contents(ht*wd, ' '){ } // 2\n        Screen(pos ht, pos wd, char c):height(ht), width(wd), contents(ht*wd, c){ } // 3\n\n        char get() const { return contents[cursor]; }\n        char get(pos r, pos c) const { return contents[r*width+c]; }\n\n    private:\n        pos cursor = 0;\n        pos height = 0, width = 0;\n        std::string contents;\n};\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_26.cpp",
    "content": "//\n//  ex7_26.cpp\n//  Exercise 7.26\n//\n//  Created by pezy on 11/9/14.\n//\n//  @Brief implementation of class Sales_data\n//  @See ex7_26.h\n\n#include \"ex7_26.h\"\n\n// member functions.\nSales_data& Sales_data::combine(const Sales_data& rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n// friend functions\nstd::istream &read(std::istream &is, Sales_data &item)\n{\n    double price = 0;\n    is >> item.bookNo >> item.units_sold >> price;\n    item.revenue = price * item.units_sold;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue;\n    return os;\n}\n\nSales_data add(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum.combine(rhs);\n    return sum;\n}\n"
  },
  {
    "path": "ch07/ex7_26.h",
    "content": "//\n//  ex7_26.h\n//  Exercise 7.26\n//\n//  Created by pezy on 11/14/14.\n//\n//  @See ex7_21.h\n//  @Add inline member function \"Sales_data::avg_pric\" \n\n#ifndef CP5_ex7_26_h\n#define CP5_ex7_26_h\n\n#include <string>\n#include <iostream>\n\nclass Sales_data {\n    friend std::istream &read(std::istream &is, Sales_data &item);\n    friend std::ostream &print(std::ostream &os, const Sales_data &item);\n    friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs);\n\npublic:\n    Sales_data() = default;\n    Sales_data(const std::string &s):bookNo(s) { }\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data(std::istream &is) { read(is, *this); }\n\n    std::string isbn() const { return bookNo; };\n    Sales_data& combine(const Sales_data&);\n    \nprivate:\n    inline double avg_price() const;        \n\nprivate:\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\ninline\ndouble Sales_data::avg_price() const\n{\n    return units_sold ? revenue/units_sold : 0;\n}\n\n// declarations for nonmember parts of the Sales_data interface.\nstd::istream &read(std::istream &is, Sales_data &item);\nstd::ostream &print(std::ostream &os, const Sales_data &item);\nSales_data add(const Sales_data &lhs, const Sales_data &rhs);\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_27.h",
    "content": "//\n//  ex7_27.h\n//  Exercise 7.27\n//\n//  Created by pezy on 11/14/14.\n//\n\n#ifndef CP5_ex7_27_h\n#define CP5_ex7_27_h\n\n#include <string>\n#include <iostream>\n\nclass Screen {\npublic:\n    using pos = std::string::size_type;\n\n    Screen() = default; // 1\n    Screen(pos ht, pos wd):height(ht), width(wd), contents(ht*wd, ' '){ } // 2\n    Screen(pos ht, pos wd, char c):height(ht), width(wd), contents(ht*wd, c){ } // 3\n\n    char get() const { return contents[cursor]; }\n    char get(pos r, pos c) const { return contents[r*width+c]; }\n    inline Screen& move(pos r, pos c);\n    inline Screen& set(char c);\n    inline Screen& set(pos r, pos c, char ch);\n\n    const Screen& display(std::ostream &os) const { do_display(os); return *this; }\n    Screen& display(std::ostream &os) { do_display(os); return *this; }\n\nprivate:\n    void do_display(std::ostream &os) const { os << contents; }\n\nprivate:\n    pos cursor = 0;\n    pos height = 0, width = 0;\n    std::string contents;\n};\n\ninline Screen& Screen::move(pos r, pos c)\n{\n    cursor = r*width + c;\n    return *this;\n}\n\ninline Screen& Screen::set(char c)\n{\n    contents[cursor] = c;\n    return *this;\n}\n\ninline Screen& Screen::set(pos r, pos c, char ch)\n{\n    contents[r*width+c] = ch;\n    return *this;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_27_TEST.cpp",
    "content": "//\n//  ex7_27_TEST.cpp\n//  Test of Exercise 7.27\n//\n//  Created by pezy on 11/14/14.\n//\n\n#include \"ex7_27.h\"\n\nint main()\n{\n    Screen myScreen(5, 5, 'X');\n    myScreen.move(4, 0).set('#').display(std::cout);\n    std::cout << \"\\n\";\n    myScreen.display(std::cout);\n    std::cout << \"\\n\";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_31.h",
    "content": "//\n//  ex7_31.h\n//  Exercise 7.31\n//\n//  Created by pezy on 11/17/14.\n//\n\n#ifndef CP5_ex7_31_h\n#define CP5_ex7_31_h\n\nclass Y;\n\nclass X {\n    Y* y = nullptr;\n};\n\nclass Y {\n    X x;\n};\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_32.h",
    "content": "//\n//  ex7_32.h\n//  Exercise 7.32 \n//\n//  Created by pezy on 11/18/14.\n//\n//  @See ex7_27.h\n\n#ifndef CP5_ex7_32_h\n#define CP5_ex7_32_h\n\n#include <vector>\n#include <string>\n#include <iostream>\n\nclass Screen;\n\nclass Window_mgr {\npublic:\n    using ScreenIndex = std::vector<Screen>::size_type;\n    inline void clear(ScreenIndex);\nprivate:\n    std::vector<Screen> screens;\n};\n\nclass Screen {\n    friend void Window_mgr::clear(ScreenIndex);\npublic:\n    using pos = std::string::size_type;\n\n    Screen() = default; // 1\n    Screen(pos ht, pos wd):height(ht), width(wd), contents(ht*wd, ' '){ } // 2\n    Screen(pos ht, pos wd, char c):height(ht), width(wd), contents(ht*wd, c){ } // 3\n\n    char get() const { return contents[cursor]; }\n    char get(pos r, pos c) const { return contents[r*width+c]; }\n    inline Screen& move(pos r, pos c);\n    inline Screen& set(char c);\n    inline Screen& set(pos r, pos c, char ch);\n\n    const Screen& display(std::ostream &os) const { do_display(os); return *this; }\n    Screen& display(std::ostream &os) { do_display(os); return *this; }\n\nprivate:\n    void do_display(std::ostream &os) const { os << contents; }\n\nprivate:\n    pos cursor = 0;\n    pos height = 0, width = 0;\n    std::string contents;\n};\n\ninline void Window_mgr::clear(ScreenIndex i)\n{ \n    if (i >= screens.size()) return;    // judge for out_of_range.\n    Screen &s = screens[i];\n    s.contents = std::string(s.height * s.width, ' ');\n}\n\ninline Screen& Screen::move(pos r, pos c)\n{\n    cursor = r*width + c;\n    return *this;\n}\n\ninline Screen& Screen::set(char c)\n{\n    contents[cursor] = c;\n    return *this;\n}\n\ninline Screen& Screen::set(pos r, pos c, char ch)\n{\n    contents[r*width+c] = ch;\n    return *this;\n}\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_41.cpp",
    "content": "//\n//  ex7_41.cpp\n//  Exercise 7.41\n//\n//  Created by pezy on 11/20/14.\n//\n//  @Brief implementation of class Sales_data\n//  @See ex7_41.h\n\n#include \"ex7_41.h\"\n\n// constructor\nSales_data::Sales_data(std::istream &is) : Sales_data()\n{\n    std::cout << \"Sales_data(istream &is)\" << std::endl;\n    read(is, *this);\n}\n\n// member functions.\nSales_data& Sales_data::combine(const Sales_data& rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n// friend functions\nstd::istream &read(std::istream &is, Sales_data &item)\n{\n    double price = 0;\n    is >> item.bookNo >> item.units_sold >> price;\n    item.revenue = price * item.units_sold;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue;\n    return os;\n}\n\nSales_data add(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum.combine(rhs);\n    return sum;\n}\n"
  },
  {
    "path": "ch07/ex7_41.h",
    "content": "//\n//  ex7_41.h\n//  Exercise 7.41 \n//\n//  Created by pezy on 11/20/14.\n//\n//  @See ex7_26.h\n//  @Add 1. use delegating constructors\n//       2. add a statement to the body of each of the constructors that prints a message whether it is executed. \n\n#ifndef CP5_ex7_41_h\n#define CP5_ex7_41_h\n\n#include <string>\n#include <iostream>\n\nclass Sales_data {\n    friend std::istream &read(std::istream &is, Sales_data &item);\n    friend std::ostream &print(std::ostream &os, const Sales_data &item);\n    friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs);\n\npublic:\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p)\n    { std::cout << \"Sales_data(const std::string&, unsigned, double)\" << std::endl; }\n    \n    Sales_data() : Sales_data(\"\", 0, 0.0f)\n    { std::cout << \"Sales_data()\" << std::endl; }\n    \n    Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f)\n    { std::cout << \"Sales_data(const std::string&)\" << std::endl; }\n    \n    Sales_data(std::istream &is);\n\n    std::string isbn() const { return bookNo; }\n    Sales_data& combine(const Sales_data&);\n    \nprivate:\n    inline double avg_price() const;        \n\nprivate:\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\ninline\ndouble Sales_data::avg_price() const\n{\n    return units_sold ? revenue/units_sold : 0;\n}\n\n// declarations for nonmember parts of the Sales_data interface.\nstd::istream &read(std::istream &is, Sales_data &item);\nstd::ostream &print(std::ostream &os, const Sales_data &item);\nSales_data add(const Sales_data &lhs, const Sales_data &rhs);\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_41_TEST.cpp",
    "content": "//\n//  ex7_41_TEST.cpp\n//  Test of Exercise 7.41\n//\n//  Created by pezy on 11/14/14.\n//\n\n#include \"ex7_41.h\"\nusing std::cout; using std::endl;\n\nint main()\n{\n    cout << \"1. default way: \" << endl;\n    cout << \"----------------\" << endl;\n    Sales_data s1;   \n    \n    cout << \"\\n2. use std::string as parameter: \" << endl;\n    cout << \"----------------\" << endl;\n    Sales_data s2(\"CPP-Primer-5th\");\n    \n    cout << \"\\n3. complete parameters: \" << endl;\n    cout << \"----------------\" << endl;\n    Sales_data s3(\"CPP-Primer-5th\", 3, 25.8);\n    \n    cout << \"\\n4. use istream as parameter: \" << endl;\n    cout << \"----------------\" << endl;\n    Sales_data s4(std::cin);\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_43.cpp",
    "content": "//\n//  ex7_43.cpp\n//  Exercise 7.43\n//\n//  Created by pezy on 11/20/14.\n//\n\n#include <vector> \n\nclass NoDefault {\npublic:\n    NoDefault(int i) { }\n};\n\nclass C {\npublic:\n    C() : def(0) { } // define the constructor of C.\nprivate:\n    NoDefault def;\n};\n\nint main()\n{\n    C c;\n    \n    std::vector<C> vec(10); \n    return 0;\n}\n"
  },
  {
    "path": "ch07/ex7_50.h",
    "content": "//\n//  ex7_50.cpp\n//  Exercise 7.50\n//\n//  Created by pezy on 11/24/14.\n//\n//  @See ex7_22.h\n//  @Add constructors should be explicit\n\n#ifndef CP5_ex7_50_h\n#define CP5_ex7_50_h\n\n#include <string>\n#include <iostream>\n\nstruct Person {\n    friend std::istream &read(std::istream &is, Person &person);\n    friend std::ostream &print(std::ostream &os, const Person &person);\n\npublic:\n    Person() = default;\n    Person(const std::string sname, const std::string saddr):name(sname), address(saddr){ }\n    explicit Person(std::istream &is){ read(is, *this); }\n\n    std::string getName() const { return name; }\n    std::string getAddress() const { return address; }\nprivate:\n    std::string name;\n    std::string address;\n};\n\nstd::istream &read(std::istream &is, Person &person)\n{\n    is >> person.name >> person.address;\n    return is;\n}\n\nstd::ostream &print(std::ostream &os, const Person &person)\n{\n    os << person.name << \" \" << person.address;\n    return os;\n}\n\n#endif\n\n"
  },
  {
    "path": "ch07/ex7_53.h",
    "content": "//\n//  ex7_53.h\n//  Exercise 7.53\n//\n//  Created by pezy on 11/25/14.\n//\n\n#ifndef CP5_ex7_53_h\n#define CP5_ex7_53_h\n\nclass Debug {\npublic:\n    constexpr Debug(bool b = true) : rt(b), io(b), other(b) { }\n    constexpr Debug(bool r, bool i, bool o) : rt(r), io(i), other(o) { }\n    constexpr bool any() { return rt || io || other; }\n    \n    void set_rt(bool b) { rt = b; }\n    void set_io(bool b) { io = b; }\n    void set_other(bool b) { other = b; }\n    \nprivate:\n    bool rt;        // runtime error\n    bool io;        // I/O error\n    bool other;     // the others\n};\n\n#endif\n"
  },
  {
    "path": "ch07/ex7_57.h",
    "content": "//\n//  ex7_57.h\n//  Exercise 7.57\n//\n//  Created by pezy on 11/25/14.\n//\n\n#ifndef CP5_ex7_57_h\n#define CP5_ex7_57_h\n\n#include <string>\n\nclass Account {\npublic:\n    void calculate() { amount += amount * interestRate; }\n    static double rate() { return interestRate; }\n    static void rate(double newRate) { interestRate = newRate; }\n    \nprivate:\n    std::string owner;\n    double amount;\n    static double interestRate;\n    static constexpr double todayRate = 42.42;\n    static double initRate() { return todayRate; }\n};\n\ndouble Account::interestRate = initRate();\n\n#endif\n"
  },
  {
    "path": "ch08/README.md",
    "content": "# Chapter 8. The IO Library\n\n## Exercise 8.1:\n>Write a function that takes and returns an istream&. The function should read the stream until it hits end-of-file. The function should print what it reads to the standard output. Reset the stream so that it is valid before returning the stream.\n\n```cpp\nstd::istream& func(std::istream &is)\n{\n    std::string buf;\n    while (is >> buf)\n        std::cout << buf << std::endl;\n    is.clear();\n    return is;\n}\n```\n\n## [Exercise 8.2](ex8_02.cpp)\n\n## Exercise 8.3:\n>What causes the following while to terminate?\n```cpp\nwhile (cin >> i) /*  ...    */\n```\n\nputting `cin` in an error state cause to terminate. such as `eofbit`, `failbit` and `badbit`.\n\n## [Exercise 8.4](ex8_04.cpp)\n## [Exercise 8.5](ex8_05.cpp)\n## [Exercise 8.6](ex8_06.cpp)\n## [Exercise 8.7](ex8_07.cpp)\n## [Exercise 8.8](ex8_08.cpp)\n## [Exercise 8.9](ex8_09.cpp)\n## [Exercise 8.10](ex8_10.cpp)\n## [Exercise 8.11](ex8_11.cpp)\n\n## Exercise 8.12:\n>Why didn’t we use in-class initializers in PersonInfo?\n\nCause we need a aggregate class here. so it should have no in-class initializers.\n\n## [Exercise 8.13](ex8_13.cpp)\n\n## Exercise 8.14:\n>Why did we declare entry and nums as const auto &?\n\n- cause they are all class type, not the built-in type. so **reference** more effective.\n- output shouldn't change their values. so we added the `const`.\n"
  },
  {
    "path": "ch08/ex8_02.cpp",
    "content": "//\n//  ex8_02.cpp\n//  Exercise 8.2\n//\n//  Created by pezy on 11/27/14.\n//\n//  @Brief  Test your function by calling it, passing cin as an argument\n\n#include <iostream>\nusing std::istream;\n\nistream& func(istream &is)\n{\n    std::string buf;\n    while (is >> buf)\n        std::cout << buf << std::endl;\n    is.clear();\n    return is;\n}\n\nint main()\n{\n    istream& is = func(std::cin);\n    std::cout << is.rdstate() << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_04.cpp",
    "content": "//\n//  ex8_04.cpp\n//  Exercise 8.4\n//\n//  Created by pezy on 11/9/14.\n//\n//  @Brief  Write a function to open a file for input and read its contents into a vector of strings, \n//          storing each line as a separate element in the vector. \n\n#include <fstream>\n#include <string>\n#include <vector>\n#include <iostream>\n\nusing std::vector; using std::string; using std::ifstream; using std::cout; using std::endl;\n\nvoid ReadFileToVec(const string& fileName, vector<string>& vec)\n{\n    ifstream ifs(fileName);\n    if (ifs)\n    {\n        string buf;\n        while (std::getline(ifs, buf))\n            vec.push_back(buf);\n    }\n}\n\nint main()\n{\n    vector<string> vec;\n    ReadFileToVec(\"../data/book.txt\", vec);\n    for (const auto &str : vec)\n        cout << str << endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_05.cpp",
    "content": "//\n//  ex8_05.cpp\n//  Exercise 8.5\n//\n//  Created by pezy on 11/9/14.\n//\n//  @Brief  Rewrite the previous program to store each word in a separate element.\n//  @See    ex8_04.cpp \n\n#include <fstream>\n#include <string>\n#include <vector>\n#include <iostream>\n\nusing std::vector; using std::string; using std::ifstream; using std::cout; using std::endl;\n\nvoid ReadFileToVec(const string& fileName, vector<string>& vec)\n{\n    ifstream ifs(fileName);\n    if (ifs)\n    {\n        string buf;\n        while (ifs >> buf)\n            vec.push_back(buf);\n    }\n}\n\nint main()\n{\n    vector<string> vec;\n    ReadFileToVec(\"../data/book.txt\", vec);\n    for (const auto &str : vec)\n        cout << str << endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_06.cpp",
    "content": "//\n//  ex8_06.cpp\n//  Exercise 8.6\n//\n//  Created by pezy on 11/27/14.\n//\n//  @Brief  Rewrite the bookstore program from 7.1.1 (p.256) to read its transactions from a file. \n//          Pass the name of the file as an argument to main (6.2.5, p.218). \n//  @See    ex7_26.h (use the Sales_data)\n//  @Run    give a parameter: \"../data/book.txt\"\n//  @Output 0-201-78345-X 5 110\n//          0-201-78346-X 9 839.2 \n\n#include <fstream>\n#include <iostream>\n\n#include \"../ch07/ex7_26.h\"\nusing std::ifstream; using std::cout; using std::endl; using std::cerr;\n\nint main(int argc, char **argv)\n{\n    ifstream input(argv[1]);\n    \n    Sales_data total;\n    if (read(input, total))\n    {\n        Sales_data trans;\n        while (read(input, trans))\n        {\n            if (total.isbn() == trans.isbn())\n                total.combine(trans);\n            else\n            {\n                print(cout, total) << endl;\n                total = trans;\n            }\n        }\n        print(cout, total) << endl;\n    }\n    else\n    {\n        cerr << \"No data?!\" << endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_07.cpp",
    "content": "//\n//  ex8_07.cpp\n//  Exercise 8.7\n//\n//  Created by pezy on 11/28/14.\n//\n//  @Brief  Revise the bookstore program from the previous section to write its output to a file.\n//          Pass the name of that file as a second argument to main.\n//  @See    ex8_06.cpp\n//  @Run    give a parameter: \"../data/book.txt ../data/out.txt\"\n\n#include <fstream>\n#include <iostream>\n\n#include \"../ch07/ex7_26.h\"\nusing std::ifstream; using std::ofstream; using std::endl; using std::cerr;\n\nint main(int argc, char **argv)\n{\n    ifstream input(argv[1]);\n    ofstream output(argv[2]);\n    \n    Sales_data total;\n    if (read(input, total))\n    {\n        Sales_data trans;\n        while (read(input, trans))\n        {\n            if (total.isbn() == trans.isbn())\n                total.combine(trans);\n            else\n            {\n                print(output, total) << endl;\n                total = trans;\n            }\n        }\n        print(output, total) << endl;\n    }\n    else\n    {\n        cerr << \"No data?!\" << endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_08.cpp",
    "content": "//\n//  ex8_08.cpp\n//  Exercise 8.8\n//\n//  Created by pezy on 11/28/14.\n//\n//  @Brief  Revise the program from the previous exercise to append its output to its given file.\n//          Run the program on the same output file at least twice to ensure that the data are preserved\n//  @See    ex8_07.cpp\n//  @Run    give a parameter: \"../data/book.txt ../data/out.txt\"\n\n#include <fstream>\n#include <iostream>\n\n#include \"../ch07/ex7_26.h\"\nusing std::ifstream; using std::ofstream; using std::endl; using std::cerr;\n\nint main(int argc, char **argv)\n{\n    ifstream input(argv[1]);\n    ofstream output(argv[2], ofstream::app);\n    \n    Sales_data total;\n    if (read(input, total))\n    {\n        Sales_data trans;\n        while (read(input, trans))\n        {\n            if (total.isbn() == trans.isbn())\n                total.combine(trans);\n            else\n            {\n                print(output, total) << endl;\n                total = trans;\n            }\n        }\n        print(output, total) << endl;\n    }\n    else\n    {\n        cerr << \"No data?!\" << endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_09.cpp",
    "content": "//\n//  ex8_09.cpp\n//  Exercise 8.9\n//\n//  Created by pezy on 11/29/14.\n//\n//  @Brief  Use the function you wrote for the first exercise in § 8.1.2 (p.314) to print the contents of an istringstream object.\n//  @See    Exercise 8.1\n\n#include <iostream>\n#include <sstream>\nusing std::istream;\n\nistream& func(istream &is)\n{\n    std::string buf;\n    while (is >> buf)\n        std::cout << buf << std::endl;\n    is.clear();\n    return is;\n}\n\nint main()\n{\n    std::istringstream iss(\"hello\");\n    func(iss);\n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_10.cpp",
    "content": "//\n//  ex8_10.cpp\n//  Exercise 8.10\n//\n//  Created by pezy on 11/29/14.\n//\n//  @Brief  Write a program to store each line from a file in a vector<string>.\n//          Now use an istringstream to read each element from the vector a word at a time.\n\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <vector>\n#include <string>\n\nusing std::vector; using std::string; using std::ifstream; using std::istringstream; using std::cout; using std::endl; using std::cerr;\n\nint main()\n{\n    ifstream ifs(\"../data/book.txt\");\n    if (!ifs)\n    {\n        cerr << \"No data?\" << endl;\n        return -1;\n    }\n    \n    vector<string> vecLine;\n    string line;\n    while (getline(ifs, line))\n        vecLine.push_back(line);\n    \n    for (auto &s : vecLine)\n    {\n        istringstream iss(s);\n        string word;\n        while (iss >> word)\n            cout << word << endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_11.cpp",
    "content": "//\n//  ex8_11.cpp\n//  Exercise 8.11\n//\n//  Created by pezy on 11/29/14.\n//\n//  @Brief  The program in this section defined its istringstream object inside the outer while loop.\n//          What changes would you need to make if record were defined outside that loop?\n//          Rewrite the program, moving the definition of record outside the while, and see whether you thought of all the changes that are needed.\n\n#include <iostream>\n#include <sstream>\n#include <string>\n#include <vector>\nusing std::vector; using std::string; using std::cin; using std::istringstream;\n\nstruct PersonInfo {\n    string name;\n    vector<string> phones;\n};\n\nint main()\n{\n    string line, word;\n    vector<PersonInfo> people;\n    istringstream record;\n    while (getline(cin, line))\n    {\n        PersonInfo info;\n        record.clear();\n        record.str(line);\n        record >> info.name;\n        while (record >> word)\n            info.phones.push_back(word);\n        people.push_back(info);\n    }\n    \n    for (auto &p : people)\n    {\n        std::cout << p.name << \" \";\n        for (auto &s : p.phones)\n            std::cout << s << \" \";\n        std::cout << std::endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch08/ex8_13.cpp",
    "content": "//\n//  ex8_13.cpp\n//  Exercise 8.13\n//\n//  Created by pezy on 11/29/14.\n//\n//  @Brief  Rewrite the phone number program from this section to read from\n//          a named file rather than from cin.\n//  @See    ex8_11.cpp\n\n#include <iostream>\n#include <sstream>\n#include <fstream>\n#include <string>\n#include <vector>\n\nusing std::vector; using std::string; using std::cin; using std::istringstream;\nusing std::ostringstream; using std::ifstream; using std::cerr; using std::cout; using std::endl;\nusing std::isdigit;\n\nstruct PersonInfo {\n    string name;\n    vector<string> phones;\n};\n\nbool valid(const string& str)\n{\n    return isdigit(str[0]);\n}\n\nstring format(const string& str)\n{\n    return str.substr(0,3) + \"-\" + str.substr(3,3) + \"-\" + str.substr(6);\n}\n\nint main()\n{\n    ifstream ifs(\"../data/phonenumbers.txt\");\n    if (!ifs)\n    {\n        cerr << \"no phone numbers?\" << endl;\n        return -1;\n    }\n\n    string line, word;\n    vector<PersonInfo> people;\n    istringstream record;\n    while (getline(ifs, line))\n    {\n        PersonInfo info;\n        record.clear();\n        record.str(line);\n        record >> info.name;\n        while (record >> word)\n            info.phones.push_back(word);\n        people.push_back(info);\n    }\n\n    for (const auto &entry : people)\n    {\n        ostringstream formatted, badNums;\n        for (const auto &nums : entry.phones)\n            if (!valid(nums)) badNums << \" \" << nums;\n            else formatted << \" \" << format(nums);\n        if (badNums.str().empty())\n            cout << entry.name << \" \" << formatted.str() << endl;\n        else\n            cerr << \"input error: \" << entry.name\n                 << \" invalid number(s) \" << badNums.str() << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/README.md",
    "content": "﻿# Chapter 9. Sequential Containers\n\n## Exercise 9.1:\n>Which is the most appropriate—a vector, a deque, or a list—for the following program tasks?Explain the rationale for your choice.If there is no reason to prefer one or another container, explain why not.\n\n>- (a) Read a fixed number of words, inserting them in the container alphabetically as they are entered. We’ll see in the next chapter that associative containers are better suited to this problem.\n>- (b) Read an unknown number of words. Always insert new words at the back. Remove the next value from the front.\n>- (c) Read an unknown number of integers from a file. Sort the numbers and then print them to standard output.\n\n- (a) Within the three options, `std::list` is the best one. To keep sorted alphabetically, each inserting into vector takes theta(n) time complexity, whereas that of list (essentially doubly linked list) takes only O(n). Hence theoretically list has better performance.  \n- (b) `deque`. If the program needs to insert or delete elements at the front and the back, but not in the middle, use a deque\n- (c) `vector`, no need that insert or delete at the front or back. and If your program has lots of small elements and space overhead matters, don’t use list or forward_list.\n\n## Exercise 9.2:\n>Define a list that holds elements that are deques that hold ints.\n\n```cpp\nstd::list<std::deque<int>> a_list_of_deque_of_ints;\n```\n\n## Exercise 9.3:\n>What are the constraints on the iterators that form iterator ranges?\n\ntwo iterators, `begin` and `end`:\n- they refer to elements of the same container.\n- It is possible to reach `end` by repeatedly incrementing `begin`.\n\n## Exercise 9.4:\n>Write a function that takes a pair of iterators to a vector<int> and an int value. Look for that value in the range and return a bool indicating whether it was found.\n\n```cpp\nbool contains(vector<int>::const_iterator first, vector<int>::const_iterator last, int value)\n{\n    for(; first != last; ++first)\n        if(*first == value) return true;\n    return false;\n}\n```\n\n## Exercise 9.5:\n>Rewrite the previous program to return an iterator to the requested element. Note that the program must handle the case where the element is not found.\n\n```cpp\nauto find(vector<int>::const_iterator first, vector<int>::const_iterator last, int value)\n{\n    for(; first != last; ++first)\n        if(*first == value) return first;\n    return last;\n}\n```\n\n## Exercise 9.6:\n>What is wrong with the following program? How might you correct it?\n\n```cpp\nlist<int> lst1;\nlist<int>::iterator iter1 = lst1.begin(), iter2 = lst1.end();\nwhile (iter1 < iter2)\n```\n\nFixed:\n```cpp\nwhile(iter1 != iter2)\n```\n#### note:\noperator `<` is not implemented in `std::list`, because `std::list` is essetially a doubly linked list. Addresses of nodes of linked list are not necessarily continuous.  \n## Exercise 9.7:\n>What type should be used as the index into a vector of ints?\n\n    vector<int>::size_type\n\n## Exercise 9.8:\n>What type should be used to read elements in a list of strings? To write them?\n\n    list<string>::const_iterator // to read\n    list<string>::iterator // to write\n\n## Exercise 9.9:\n>What is the difference between the `begin` and `cbegin` functions?\n\n`cbegin` is a const member that returns the container’s **const_iterator** type.\n\n`begin` is nonconst and returns the container’s **iterator** type.\n\n## Exercise 9.10:\n>What are the types of the following four objects?\n```cpp\nvector<int> v1;\nconst vector<int> v2;\nauto it1 = v1.begin(), it2 = v2.begin();\nauto it3 = v1.cbegin(), it4 = v2.cbegin();\n```\n\n-----\n\n[@shidenggui](https://github.com/shidenggui):\n\nThe question example codes have an error in `gcc 4.8`:\n>**error**: inconsistent deduction for ‘auto’: ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’ and then ‘__gnu_cxx::__normal_iterator<const int*, std::vector<int> >’ auto it1 = v1.begin(), it2 = v2.begin();\n\nthe correct codes should be:\n```cpp\nauto it1 = v1.begin();\nauto it2 = v2.begin(), it3 = v1.cbegin(), it4 = v2.cbegin();\n```\n\n-----\n\n`it1` is `vector<int>::iterator`\n\n`it2`, `it3` and `it4` are `vector<int>::const_iterator`\n\n## Exercise 9.11:\n>Show an example of each of the six ways to create and initialize a vector. Explain what values each vector contains.\n\n```cpp\nvector<int> vec;    // vec is empty\nvector<int> vec(10);    // 0\nvector<int> vec(10, 1);  // 1\nvector<int> vec{ 1, 2, 3, 4, 5 }; // 1, 2, 3, 4, 5\nvector<int> vec(other_vec); // same as other_vec\nvector<int> vec(other_vec.begin(), other_vec.end()); // same as other_vec\n```\n\n## Exercise 9.12:\n>Explain the differences between the constructor that takes a container to copy and the constructor that takes two iterators.\n\n- The constructor that takes another container as an argument (excepting array) assumes the container type and element type of both containers are identical. It will also copy all the elements of the received container into the new one:\n```cpp\nlist<int> numbers = { 1, 2, 3, 4, 5 };\nlist<int> numbers2(numbers);        // ok, numbers2 has the same elements as numbers\nvector<int> numbers3(numbers);      // error: no matching function for call...\nlist<double> numbers4(numbers);     // error: no matching function for call...\n```\n- The constructor that takes two iterators as arguments does not require the container types to be identical. Moreover, the element types in the new and original containers can differ as long as it is possible to convert the elements we’re copying to the element type of the container we are initializing.\nIt will also copy only the object delimited by the received iterators.\n```cpp\nlist<int> numbers = { 1, 2, 3, 4, 5 };\nlist<int> numbers2(numbers.begin(), numbers.end);        // ok, numbers2 has the same elements as numbers\nvector<int> numbers3(numbers.begin(), --numbers.end());  // ok, numbers3 is { 1, 2, 3, 4 }\nlist<double> numbers4(++numbers.beg(), --numbers.end());        // ok, numbers4 is { 2, 3, 4 }\nforward_list<float> numbers5(numbers.begin(), numbers.end());   // ok, number5 is { 1, 2, 3, 4, 5 }\n```\n\n\n## [Exercise 9.13](ex9_13.cpp)\n## [Exercise 9.14](ex9_14.cpp)\n## [Exercise 9.15](ex9_15.cpp)\n## [Exercise 9.16](ex9_16.cpp)\n\n## Exercise 9.17:\n>Assuming c1 and c2 are containers, what (if any) constraints does the following usage place on the types of c1 and c2?\n\nFirst, there must be the identical container and same type holded.\nSecond, the type held must support relational operation. (@Mooophy)\n\nBoth c1 and c2 are the containers except the unordered associative containers.(@pezy)\n\n## [Exercise 9.18](ex9_18.cpp)\n## [Exercise 9.19](ex9_19.cpp)\n## [Exercise 9.20](ex9_20.cpp)\n\n## Exercise 9.21:\n>Explain how the loop from page 345 that used the return from insert to add elements to a list would work if we inserted into a vector instead.\n\nIt's the same.\n>The first call to `insert` takes the `string` we just read and puts it in front of the element denoted by `iter`. The value returned by `insert` is an iterator referring to this new element. We assign that iterator to `iter` and repeat the `while`, reading another word. As long as there are words to insert, each trip through the `while` inserts a new element ahead of `iter` and reassigns to `iter` the location of the newly inserted element. That element is the (new) first element. Thus, each iteration inserts an element ahead of the first element in the `vector`.\n\n## Exercise 9.22:\n>Assuming `iv` is a `vector` of `int`s, what is wrong with the following program? How might you correct the problem(s)?\n```cpp\nvector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size()/2;\nwhile (iter != mid)\n    if (*iter == some_val)\n        iv.insert(iter, 2 * some_val);\n```\n\n**Problems:**\n\n1. It's a endless loop. `iter` never equal `mid`.\n2. mid will be invalid after the `insert`.(see [issue 133](https://github.com/Mooophy/Cpp-Primer/issues/133))\n\n**FIXED**:\n\n```cpp\n// cause the reallocation will lead the iterators and references\n// after the insertion point to invalid. Thus, we need to call reserver at first.\n\n#include <iostream>\n#include <vector>\n\nvoid double_and_insert(std::vector<int>& v, int some_val)\n{\n    auto mid = [&]{ return v.begin() + v.size() / 2; };\n    for (auto curr = v.begin(); curr != mid(); ++curr)\n        if (*curr == some_val)\n            ++(curr = v.insert(curr, 2 * some_val));\n}\n\nint main()\n{\n    std::vector<int> v{ 1, 9, 1, 9, 9, 9, 1, 1 };\n    double_and_insert(v, 1);\n\n    for (auto i : v) \n        std::cout << i << std::endl;\n}\n```\n\nThe complete test codes, check [this](ex9_22.cpp).\n\n## Exercise 9.23:\n>In the first program in this section on page 346, what would\nthe values of val, val2, val3, and val4 be if c.size() is 1?\n\nsame value that equal to the first element's.\n\n## [Exercise 9.24](ex9_24.cpp)\n\n## Exercise 9.25:\n>In the program on page 349 that erased a range of\nelements, what happens if elem1 and elem2 are equal? What if elem2 or both elem1 and elem2 are the off-the-end iterator?\n\nif elem1 and elem2 are equal, nothing happened.\n\nif elem2 is the off-the-end iterator, it would delete from elem1 to the end.\n\nif both elem1 and elem2 are the off-the-end iterator, nothing happened too.\n\n## [Exercise 9.26](ex9_26.cpp)\n## [Exercise 9.27](ex9_27.cpp)\n\n## Exercise 9.28:\n>Write a function that takes a forward_list<string> and two additional string arguments. The function should find the first string and insert the second immediately following the first. If the first string is not found, then insert the second string at the end of the list.\n\n```cpp\nvoid find_and_insert(forward_list<string> &list, string const& to_find, string const& to_add)\n{\n    auto prev = list.before_begin();\n    for (auto curr = list.begin(); curr != list.end(); prev = curr++)\n    {\n        if (*curr == to_find)\n        {\n            list.insert_after(curr, to_add);\n            return;\n        }\n    }\n    list.insert_after(prev, to_add);\n}\n```\n\n## Exercise 9.29:\n>Given that vec holds 25 elements, what does\nvec.resize(100) do? What if we next wrote vec.resize(10)?\n\n```cpp\nvec.resize(100);    // adds 75 elements of value 0 to the back of vec\nvec.resize(10);     // erases 90 elements from the back of vec\n```\n\n## Exercise 9.30:\n>What, if any, restrictions does using the version of resize\nthat takes a single argument place on the element type?\n\nIf the container holds elements of a class type and resize adds elements\nwe **must supply an initializer** or the element type must have a **default constructor**.\n\n## Exercise 9.31 [use list](ex9_31_1.cpp) | [use forward_list](ex9_31_2.cpp)\n## [Exercise 9.32](ex9_32.cpp)\n## [Exercise 9.33](ex9_33.cpp)\n## [Exercise 9.34](ex9_34.cpp)\n\n## Exercise 9.35:\n>Explain the difference between a vector’s capacity and its size.\n\nThe **size** of a container is the number of **elements** it already holds;\n\nThe **capacity** is how many elements it can hold before more **space** must be allocated.\n\n## Exercise 9.36:\n>Can a container have a capacity less than its size?\n\ncannot.\n\n## Exercise 9.37:\n>Why don’t list or array have a capacity member?\n\n`list` does not hold elements contiguously. `array` has the fixed size statically.\n\n## [Exercise 9.38](ex9_38.cpp)\n\n## Exercise 9.39:\n>Explain what the following program fragment does:\n```cpp\nvector<string> svec;\nsvec.reserve(1024);\nstring word;\nwhile (cin >> word)\n    svec.push_back(word);\nsvec.resize(svec.size()+svec.size()/2);\n```\n\nThe `while` loop will read words from `cin` and store them in out vector. Even if we initially reserved 1024 elements, if there are more words read from `cin`, our vector's capacity will be automatically increased (most implementations will double the previous capacity) to accommodate them.\n\nAnd now comes the catch. `resize()` is different from `reserve()`. In this case `resize()` will add another `svec.size()/2` value initialized elements to `svec`. If this exceeds `svec.capacity()` it will also automatically increase it to accommodate the new elements.\n\n## Exercise 9.40:\n>If the program in the previous exercise reads 256 words, what is its likely capacity after it is resized? What if it reads 512? 1, 000? 1, 048?\n\nread | size | capacity\n------ | ------ | ------\n256 | 384 | 1024\n512 | 768 | 1024\n1000 | 1500 | 2000(clang is 2048)\n1048 | 1572 | 2048\n\n## [Exercise 9.41](ex9_41.cpp)\n\n## Exercise 9.42:\n>Given that you want to read a character at a time into a string, and you know that you need to read at least 100 characters, how might you improve the performance of your program?\n\nUse member `reserve(120)` to allocate enough space for this string. (@Mooophy)\n\n## [Exercise 9.43](ex9_43.cpp)\n\n## [Exercise 9.44](ex9_44.cpp)\n## [Exercise 9.45](ex9_45.cpp)\n## [Exercise 9.46](ex9_46.cpp)\n## Exercise 9.47 [find_first_of](ex9_47_1.cpp) | [find_first_not_of](ex9_47_2.cpp)\n## Exercise 9.48:\n>Given the definitions of name and numbers on page 365,\nwhat does numbers.find(name) return?\n\nstring::npos\n\n## [Exercise 9.49](ex9_49.cpp)\n## [Exercise 9.50](ex9_50.cpp)\n## [Exercise 9.51](ex9_51.cpp)\n## [Exercise 9.52](ex9_52.cpp)\n"
  },
  {
    "path": "ch09/ex9_13.cpp",
    "content": "// @author @shbling @Yue Wang\n//\n// Exercise 9.13:\n// How would you initialize a vector<double> from a list<int>?\n// From a vector<int>?\n// Write code to check your answers.\n//\n#include <iostream>\n#include <string>\n#include <vector>\n#include <list>\n\nusing std::list; using std::vector; using std::cout; using std::endl;\n\nint main()\n{\n    list<int> ilst(5, 4);\n    vector<int> ivc(5, 5);\n\n    // from list<int> to vector<double>\n    vector<double> dvc(ilst.begin(), ilst.end());\n    for (auto i : ilst) cout << i << \" \";\n    cout << endl;\n    for (auto d : dvc) cout << d << \" \";\n    cout << endl;\n\n    // from vector<int> to vector<double>\n    vector<double> dvc2(ivc.begin(), ivc.end());\n    for (auto i : ivc) cout << i << \" \";\n    cout << endl;\n    for (auto d : dvc2) cout << d << \" \";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_14.cpp",
    "content": "// @Yue Wang @pezy\n//\n// Exercise 9.14:\n// Write a program to assign the elements from a list of char* pointers\n// to C-style character strings\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <list>\n\nint main()\n{\n    std::list<const char*> l{ \"Mooophy\", \"pezy\", \"Queeuqueg\" };\n    std::vector<std::string> v;\n    v.assign(l.cbegin(), l.cend());\n    for (auto ptr : v)\n        std::cout << ptr << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_15.cpp",
    "content": "//\n//  ex9_15.cpp\n//  Exercise 9.15\n//\n//  Created by pezy on 12/2/14.\n//\n//  @Brief  Write a program to determine whether two vector<int>s are equal.\n\n#include <iostream>\n#include <vector>\n\nint main()\n{\n    std::vector<int> vec1{ 1, 2, 3, 4, 5 };\n    std::vector<int> vec2{ 1, 2, 3, 4, 5 };\n    std::vector<int> vec3{ 1, 2, 3, 4 };\n\n    std::cout << (vec1 == vec2 ? \"true\" : \"false\") << std::endl;\n    std::cout << (vec1 == vec3 ? \"true\" : \"false\") << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_16.cpp",
    "content": "//\n//  ex9_16.cpp\n//  Exercise 9.16\n//\n//  Created by pezy on 12/2/14.\n//\n//  @Brief  Repeat the previous program, but compare elements in a\n//          list<int> to a vector<int>.\n//  \n//  @Refactor Yue Wang Jun 2015\n//\n\n\n#include <iostream>\n#include <vector>\n#include <list>\n\nint main()\n{\n    std::list<int>      li{ 1, 2, 3, 4, 5 };\n    std::vector<int>    vec2{ 1, 2, 3, 4, 5 };\n    std::vector<int>    vec3{ 1, 2, 3, 4 };\n\n    std::cout << (std::vector<int>(li.begin(), li.end()) == vec2 ? \"true\" : \"false\") << std::endl;\n    std::cout << (std::vector<int>(li.begin(), li.end()) == vec3 ? \"true\" : \"false\") << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_18.cpp",
    "content": "//\n//  ex9_18.cpp\n//  Exercise 9.18\n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  Write a program to read a sequence of strings from the standard input into\n//          a deque. Use iterators to write a loop to print the elements in the deque.\n\n#include <iostream>\n#include <string>\n#include <deque>\n\nusing std::string; using std::deque; using std::cout; using std::cin; using std::endl;\n\nint main()\n{\n    deque<string> input;\n    for (string str; cin >> str; input.push_back(str));\n    for (auto iter = input.cbegin(); iter != input.cend(); ++iter)\n        cout << *iter << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_19.cpp",
    "content": "//\n//  ex9_19.cpp\n//  Exercise 9.19\n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  Rewrite the program from the previous exercise to use a list.\n//          List the changes you needed to make.\n//  @See    ex9_18.cpp\n\n#include <iostream>\n#include <string>\n#include <list>\n\nusing std::string; using std::list; using std::cout; using std::cin; using std::endl;\n\nint main()\n{\n    list<string> input;\n    for (string str; cin >> str; input.push_back(str));\n    for (auto iter = input.cbegin(); iter != input.cend(); ++iter)\n        cout << *iter << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_20.cpp",
    "content": "//\n//  ex9_20.cpp\n//  Exercise 9.20\n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  Write a program to copy elements from a list<int> into two deques.\n//          The even-valued elements should go into one deque and the odd ones into the other.\n\n#include <iostream>\n#include <deque>\n#include <list>\nusing std::deque; using std::list; using std::cout; using std::cin; using std::endl;\n\nint main()\n{\n    list<int> l{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };\n    deque<int> odd, even;\n    for (auto i : l)\n        (i & 0x1 ? odd : even).push_back(i);\n\n    for (auto i : odd) cout << i << \" \";\n    cout << endl;\n    for (auto i : even)cout << i << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_22.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nvoid double_and_insert(std::vector<int>& v, int some_val)\n{\n    auto mid = [&]{ return v.begin() + v.size() / 2; };\n    for (auto curr = v.begin(); curr != mid(); ++curr)\n        if (*curr == some_val)\n            ++(curr = v.insert(curr, 2 * some_val));\n}\n\nint main()\n{\n    std::vector<int> v{ 1, 9, 1, 9, 9, 9, 1, 1 };\n    double_and_insert(v, 1);\n\n    for (auto i : v) \n        std::cout << i << std::endl;\n}\n"
  },
  {
    "path": "ch09/ex9_24.cpp",
    "content": "// @Yue Wang @pezy\n//\n// Exercise 9.24:\n// Write a program that fetches the first element in a vector using at,\n// the subscript operator, front, and begin. Test your program on an empty vector.\n//\n#include <iostream>\n#include <vector>\n\nint main()\n{\n    std::vector<int> v;\n    std::cout << v.at(0);       // terminating with uncaught exception of type std::out_of_range\n    std::cout << v[0];          // Segmentation fault: 11\n    std::cout << v.front();     // Segmentation fault: 11\n    std::cout << *v.begin();    // Segmentation fault: 11\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_26.cpp",
    "content": "//\n// @author @huangjuncmj @Yue Wang\n// @date   19.11.2014\n//\n// Exercise 9.26:\n// Using the following definition of ia, copy ia into a vector and into a list.\n// Use the single-iterator form of erase to remove the elements with odd values from your\n// list and the even values from your vector.\n//\n#include <iostream>\n#include <vector>\n#include <list>\n\nusing std::vector; using std::list; using std::cout; using std::endl; using std::end;\n\nint main()\n{\n    int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };\n\n    // init\n    vector<int> vec(ia, end(ia));\n    list<int> lst(vec.begin(), vec.end());\n\n    // remove odd value\n    for(auto it = lst.begin();  it != lst.end(); )\n        if(*it & 0x1) it = lst.erase(it);\n        else ++it;\n\n    // remove even value\n    for(auto it = vec.begin();  it != vec.end(); )\n        if(! (*it & 0x1)) it = vec.erase(it);\n        else ++it;\n\n    // print\n    cout << \"list : \";\n    for(auto i : lst)   cout << i << \" \";\n    cout << \"\\nvector : \";\n    for(auto i : vec)   cout << i << \" \";\n    cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_27.cpp",
    "content": "//\n//  ex9_27.cpp\n//  Exercise 9.27\n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  Write a program to find and remove the odd-valued\n//          elements in a forward_list<int>.\n//\n//  @Refactored by @Yue Wang Jun 2015, Oct 2015\n//\n\n#include <iostream>\n#include <forward_list>\n\nusing std::forward_list; \nusing std::cout;\n\nauto remove_odds(forward_list<int>& flist)\n{\n    auto is_odd = [] (int i) { return i & 0x1; };\n    flist.remove_if(is_odd);\n}\n\nint main()\n{\n    forward_list<int> data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    remove_odds(data);\n    for (auto i : data) \n        cout << i << \" \";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_31_1.cpp",
    "content": "//\n//  ex9_31.cpp\n//  Exercise 9.31 \n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  The program on page 354 to remove even-valued elements and \n//          duplicate odd ones will not work on a list or forward_list. Why? \n//          Revise the program so that it works on these types as well. \n//  @list   iter += 2; -> advance(iter, 2);\n//\n//  Refactored by Yue Wang Oct 2015\n//\n\n#include <iostream>\n#include <list>\n\nusing std::list;\nusing std::cout;\nusing std::advance;\n\nauto remove_evens_and_double_odds(list<int>& data)\n{\n    for(auto cur = data.begin(); cur != data.end();)\n        if (*cur & 0x1)\n            cur = data.insert(cur, *cur), advance(cur, 2);\n        else\n            cur = data.erase(cur);\n}\n\nint main()\n{\n    list<int> data { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    remove_evens_and_double_odds(data);\n    for (auto i : data) cout << i << \" \";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_31_2.cpp",
    "content": "//\n//  ex9_31.cpp\n//  Exercise 9.31 \n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  The program on page 354 to remove even-valued elements and \n//          duplicate odd ones will not work on a list or forward_list. Why? \n//          Revise the program so that it works on these types as well. \n//  \n//  Refactored by Yue Wang Oct 2015  \n//\n\n#include <iostream>\n#include <forward_list>\n\nusing std::forward_list;\nusing std::cout;\nusing std::advance;\n\nauto remove_evens_and_double_odds(forward_list<int>& data)\n{\n    for(auto cur = data.begin(), prv = data.before_begin(); cur != data.end();)\n        if (*cur & 0x1)\n            cur = data.insert_after(prv, *cur),\n            advance(cur, 2),\n            advance(prv, 2);\n        else\n            cur = data.erase_after(prv);\n}\n\nint main()\n{\n    forward_list<int> data { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    remove_evens_and_double_odds(data);\n    for (auto i : data)\n        cout << i << \" \";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_32.cpp",
    "content": "//\n//  ex9_32.cpp\n//  Exercise 9.32\n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  In the program on page 354 would it be legal to write the call to insert as follows?\n//          If not, why not?\n//          iter = vi.insert(iter, *iter++);\n//  @Answer the statement is illegal, because as said in Standard [5.2.2] :\n//          \"The order of evaluation of arguments is unspecified.\"\n//          As a result, after entering function insert,\n//          iter could be its original value or original value + 1 or even anything else,\n//          depending on how compiler implemented.\n//  @Discuss    https://github.com/Mooophy/Cpp-Primer/issues/125\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_33.cpp",
    "content": "//\n//  ex9_33.cpp\n//  Exercise 9.33 \n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  In the final example in this section what would happen \n//          if we did not assign the result of insert to begin? \n//          Write a program that omits this assignment to see if your expectation was correct.  \n//  @Answer Crash, because the iterator is invalid after inserting.\n\n#include <iostream>\n#include <vector>\n\nusing std::vector; using std::cout; using std::endl;\n\nint main()\n{\n    vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    auto begin = v.begin();\n    while (begin != v.end()) {\n        ++begin;\n        /*begin = */v.insert(begin, 42);\n        ++begin;\n    }\n\n    for (auto i : v)\n        cout << i << \" \";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_34.cpp",
    "content": "//\n//  ex9_32.cpp\n//  Exercise 9.32 \n//\n//  Created by pezy on 12/3/14.\n//\n//  @Brief  Assuming vi is a container of ints that includes even and odd values, \n//          predict the behavior of the following loop. \n//          After you've analyzed this loop, write a program to test whether your expectations were correct.\n//\t\t\t\n//\t\t\titer = vi.begin(); \n//\t\t\twhile (iter != vi.end())    \n//\t\t\t\tif (*iter % 2)        \n//\t\t\t\t\titer = vi.insert(iter, *iter);    \n//\t\t\t\t++iter; \n//\n//  @Answer \"infinite loop\". Becasue the `++iter` is outside of the scope of the `while` loop.\n//          Fixed as following.\n//\n//  Refactored by Yue Wang Oct, 2015\n//\n\n\n#include <iostream>\n#include <vector>\n\nusing std::cout;\nusing std::endl;\nusing std::vector;\n\nint main()\n{\n    vector<int> data { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    for(auto cur = data.begin(); cur != data.end(); ++cur)\n        if(*cur & 0x1)\n            cur = data.insert(cur, *cur), ++cur;\n    \n    for (auto i : data)\n        cout << i << \" \";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_38.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 9.38:\n// Write a program to explore how vectors grow in the library you use.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n\nint main()\n{\n    std::vector<std::string> v;\n    for (std::string buffer; std::cin >> buffer; v.push_back(buffer))\n        std::cout << v.capacity() << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_41.cpp",
    "content": "//\n//  ex9_41.cpp\n//  Exercise 9.41\n//\n//  Created by pezy on 12/4/14.\n//\n//  @Brief  Write a program that initializes a string from a vector<char>.\n\n#include <iostream>\n#include <vector>\n#include <string>\n\nusing std::vector; \nusing std::cout; \nusing std::endl; \nusing std::string;\n\nint main()\n{\n    vector<char> v{ 'p', 'e', 'z', 'y' };\n    string str(v.cbegin(), v.cend());\n    cout << str << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_43.cpp",
    "content": "//\n//  ex9_43.cpp\n//  Exercise 9.43\n//\n//  Created by XDXX on 4/17/2015.\n//\n//  @Brief  Write a function that takes three strings, s, oldVal, and newVal.\n//          Using iterators, and the insert and erase functions replace\n//          all instances of oldVal that appear in s by newVal.\n//\t        Test your function by using it to replace common abbreviations,\n//          such as “tho” by “though” and “thru” by “through”.\n//\n//  @note   This code doesn't compile on GCC. Please use Visual Studio 2015+ or Clang 3.6+ \n//  \n//  Refactored by Yue Wang Oct, 2015 \n//\n\n#include <iterator>\n#include <iostream>\n#include <string>\n#include <cstddef>\n\nusing std::cout; \nusing std::endl; \nusing std::string;\n\nauto replace_with(string &s, string const& oldVal, string const& newVal)\n{\n    for (auto cur = s.begin(); cur <= s.end() - oldVal.size(); )\n        if (oldVal == string{ cur, cur + oldVal.size() })\n            cur = s.erase(cur, cur + oldVal.size()),\n            cur = s.insert(cur, newVal.begin(), newVal.end()),\n            cur += newVal.size();\n        else  \n            ++cur;\n}\n\nint main()\n{\n    string s{ \"To drive straight thru is a foolish, tho courageous act.\" };\n    replace_with(s, \"tho\", \"though\");\n    replace_with(s, \"thru\", \"through\");\n    cout << s << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_44.cpp",
    "content": "//\n//  ex9_44.cpp\n//  Exercise 9.44\n//\n//  Created by XDXX on 4/17/15.\n//\n//  @Brief  Rewrite the previous function using an index and replace.\n//  @See    9.43\n//\n//  Refactored by Yue Wang Oct, 2015\n//\n\n#include <iostream>\n#include <string>\n\nusing std::cout; \nusing std::endl;\nusing std::string;\n\nauto replace_with(string &s, string const& oldVal, string const& newVal)\n{\n    for (size_t pos = 0; pos <= s.size() - oldVal.size();)\n        if (s[pos] == oldVal[0] && s.substr(pos, oldVal.size()) == oldVal)\n            s.replace(pos, oldVal.size(), newVal),\n            pos += newVal.size();\n        else\n            ++pos;\n}\n\nint main()\n{\n    string str{ \"To drive straight thru is a foolish, tho courageous act.\" };\n    replace_with(str, \"tho\", \"though\");\n    replace_with(str, \"thru\", \"through\");\n    cout << str << endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_45.cpp",
    "content": "// @author @TungWah @Yue Wang\n// @date   4 Oct, 2014. Oct, 2015.\n//\n// Exercise 9.45:\n// Write a funtion that takes a string representing a name and two other\n// strings representing a prefix, such as “Mr.” or “Ms.” and a suffix,\n// such as “Jr.” or “III”. Using iterators and the insert and append functions,\n// generate and return a new string with the suffix and prefix added to the\n// given name.\n//\n\n#include <iostream>\n#include <string>\n\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::endl;\n\n// Exercise 9.45\nauto add_pre_and_suffix(string name, string const& pre, string const& su)\n{\n    name.insert(name.begin(), pre.cbegin(), pre.cend());\n    return name.append(su);\n}\n\nint main()\n{\n    string name(\"Wang\");\n    cout << add_pre_and_suffix(name, \"Mr.\", \", Jr.\") << endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_46.cpp",
    "content": "//\n//  ex9_46.cpp\n//  Exercise 9.46\n//\n//  Created by pezy on 12/5/14.\n//\n//  @Brief  Rewrite the previous exercise using a position and length to manage the strings.\n//          This time use only the insert function.\n//  @See    9.45\n//\n//  Refactored by Yue Wang Oct, 2015\n//\n\n#include <iostream>\n#include <string>\n\nauto add_pre_and_suffix(std::string name, std::string const& pre, std::string const& su)\n{\n    name.insert(0, pre);\n    name.insert(name.size(), su);\n    return name;\n}\n\nint main()\n{\n    std::string name(\"alan\");\n    std::cout << add_pre_and_suffix(name, \"Mr.\", \",Jr.\");\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_47_1.cpp",
    "content": "//\n//  ex9_47_1.cpp\n//  Exercise 9.47\n//\n//  Created by pezy on 12/5/14.\n//\n//  @Brief  Write a program that finds each numeric character\n//          and then each alphabetic character in the string \"ab2c3d7R4E6\".\n//          Write two versions of the program. The first should use find_first_of,\n//          and the second find_first_not_of.\n//  @Version find_first_of\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::cout;\nusing std::endl;\n\nint main()\n{\n    string numbers{ \"123456789\" };\n    string alphabet{ \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" };\n    string str{ \"ab2c3d7R4E6\" };\n\n    cout << \"numeric characters: \";\n    for (int pos = 0; (pos = str.find_first_of(numbers, pos)) != string::npos; ++pos)\n        cout << str[pos] << \" \";\n    cout << \"\\nalphabetic characters: \";\n    for (int pos = 0; (pos = str.find_first_of(alphabet, pos)) != string::npos; ++pos)\n        cout << str[pos] << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_47_2.cpp",
    "content": "//\n//  ex9_47_2.cpp\n//  Exercise 9.47\n//\n//  Created by pezy on 12/5/14.\n//\n//  @Brief  Write a program that finds each numeric character\n//          and then each alphabetic character in the string \"ab2c3d7R4E6\".\n//          Write two versions of the program. The first should use find_first_of,\n//          and the second find_first_not_of.\n//  @Version find_first_not_of\n\n#include <string>\n#include <iostream>\n\nusing std::string; using std::cout; using std::endl;\n\nint main()\n{\n    string numbers{ \"0123456789\" };\n    string alphabet{ \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" };\n    string str{ \"ab2c3d7R4E6\" };\n\n    cout << \"numeric characters: \";\n    for (int pos = 0; (pos = str.find_first_not_of(alphabet, pos)) != string::npos; ++pos)\n        cout << str[pos] << \" \";\n    cout << \"\\nalphabetic characters: \";\n    for (int pos = 0; (pos = str.find_first_not_of(numbers, pos)) != string::npos; ++pos)\n        cout << str[pos] << \" \";\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_49.cpp",
    "content": "//\n//  ex9_49.cpp\n//  Exercise 9.49\n//\n//  Created by pezy on 12/5/14.\n//\n//  @Brief  A letter has an ascender if, as with d or f, part of the letter extends\n//          above the middle of the line.\n//          A letter has a descender if, as with p or g, part of the letter extends below the line.\n//          Write a program that reads a file containing words and reports the longest word\n//          that contains neither ascenders nor descenders.\n//  \n//  @Refactor  @Yue Wang Jun 2015\n//\n\n#include <string>\n#include <fstream>\n#include <iostream>\n\nusing std::string; using std::cout; using std::endl; using std::ifstream;\n\nint main()\n{\n    ifstream ifs(\"../data/letter.txt\");\n    if (!ifs) return -1;\n\n    string longest;\n    auto update_with = [&longest](string const& curr)\n    {\n        if (string::npos == curr.find_first_not_of(\"aceimnorsuvwxz\"))\n            longest = longest.size() < curr.size() ? curr : longest;\n    };\n    for (string curr; ifs >> curr; update_with(curr));\n    cout << longest << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_50.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 9.50:\n// Write a program to process a vector<string>s whose elements represent integral values.\n// Produce the sum of all the elements in that vector.\n// Change the program so that it sums of strings that represent floating-point values.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n\nauto sum_for_int(std::vector<std::string> const& v)\n{\n    int sum = 0;\n    for (auto const& s : v)\n        sum += std::stoi(s);\n    return sum;\n}\n\nauto sum_for_float(std::vector<std::string> const& v)\n{\n    float sum = 0.0;\n    for (auto const& s : v)\n        sum += std::stof(s);\n    return sum;\n}\n\nint main()\n{\n    std::vector<std::string> v = { \"1\", \"2\", \"3\", \"4.5\" };\n    std::cout << sum_for_int(v) << std::endl;\n    std::cout << sum_for_float(v) << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_51.cpp",
    "content": "// @Soyn\n//\n// Exercise 9.51:\n// Write a class that has three unsigned members representing year,\n// month, and day. Write a constructor that takes a string representing\n// a date. Your constructor should handle a variety of date formats,\n// such as January 1, 1900, 1/1/1900, Jan 1, 1900, and so on.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n/*@Soyn\n*Ex 9.51\n*Date: 2015.6.12\n*/\nusing namespace std;\nclass My_date{\nprivate:\n    unsigned year, month, day;\npublic:\n    My_date(const string &s){\n\n        unsigned tag;\n        unsigned format;\n        format = tag = 0;\n\n        // 1/1/1900\n        if(s.find_first_of(\"/\")!= string :: npos)\n        {\n            format = 0x01;\n        }\n\n        // January 1, 1900 or Jan 1, 1900\n        if((s.find_first_of(',') >= 4) && s.find_first_of(',')!= string :: npos){\n            format = 0x10;\n        }\n        else{ // Jan 1 1900\n            if(s.find_first_of(' ') >= 3\n                && s.find_first_of(' ')!= string :: npos){\n                format = 0x10;\n                tag = 1;\n            }\n        }\n\n        switch(format){\n\n        case 0x01:\n            day = stoi(s.substr(0, s.find_first_of(\"/\")));\n            month = stoi(s.substr(s.find_first_of(\"/\") + 1, s.find_last_of(\"/\")- s.find_first_of(\"/\")));\n            year = stoi(s.substr(s.find_last_of(\"/\") + 1, 4));\n\n        break;\n\n        case 0x10:\n            if( s.find(\"Jan\") < s.size() )  month = 1;\n            if( s.find(\"Feb\") < s.size() )  month = 2;\n            if( s.find(\"Mar\") < s.size() )  month = 3;\n            if( s.find(\"Apr\") < s.size() )  month = 4;\n            if( s.find(\"May\") < s.size() )  month = 5;\n            if( s.find(\"Jun\") < s.size() )  month = 6;\n            if( s.find(\"Jul\") < s.size() )  month = 7;\n            if( s.find(\"Aug\") < s.size() )  month = 8;\n            if( s.find(\"Sep\") < s.size() )  month = 9;\n            if( s.find(\"Oct\") < s.size() )  month =10;\n            if( s.find(\"Nov\") < s.size() )  month =11;\n            if( s.find(\"Dec\") < s.size() )  month =12;\n\n            char chr = ',';\n            if(tag == 1){\n                chr = ' ';\n            }\n            day = stoi(s.substr(s.find_first_of(\"123456789\"), s.find_first_of(chr) - s.find_first_of(\"123456789\")));\n\n            year = stoi(s.substr(s.find_last_of(' ') + 1, 4));\n            break;\n        }\n    }\n\n    void print(){\n        cout << \"day:\" << day << \" \" << \"month: \" << month << \" \" << \"year: \" << year;\n    }\n};\nint main()\n{\n    My_date d(\"Jan 1 1900\");\n    d.print();\n    return 0;\n}\n"
  },
  {
    "path": "ch09/ex9_52.cpp",
    "content": "//\n//  ex9_52.cpp\n//  Exercise 9.52 \n//\n//  Created by pezy on 12/5/14.\n//\n//  @Brief  Use a stack to process parenthesized expressions. \n//          When you see an open parenthesis, note that it was seen. \n//          When you see a close parenthesis after an open parenthesis, \n//          pop elements down to and including the open parenthesis off the stack. \n//          push a value onto the stack to indicate that a parenthesized expression was replaced. \n\n#include <stack>\n#include <string>\n#include <iostream>\n\nusing std::string; using std::cout; using std::endl; using std::stack;\n\nint main()\n{\n    string expression{ \"This is (pezy).\" };\n    bool bSeen = false;\n    stack<char> stk;\n    for (const auto &s : expression)\n    {\n        if (s == '(') { bSeen = true; continue; }\n        else if (s == ')') bSeen = false;\n        \n        if (bSeen) stk.push(s);\n    }\n    \n    string repstr;\n    while (!stk.empty())\n    {\n        repstr += stk.top();\n        stk.pop();\n    }\n    \n    expression.replace(expression.find(\"(\")+1, repstr.size(), repstr);\n    \n    cout << expression << endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch10/README.md",
    "content": "# Chapter 10. Generic Algorithms\n\n## [Exercise 10.1 and 10.2](ex10_01_02.cpp)\n\n## [Exercise 10.3 and 10.4](ex10_03_04.cpp)\n\n## Exercise 10.5:\n>In the call to equal on rosters, what would happen if both rosters held C-style strings, rather than library strings?\n\nFor such case, std::equal is going to compare the address value rather than the string value. \nSo the result is not the same as std::string. Try to avoid coding this way. Check [#227](https://github.com/Mooophy/Cpp-Primer/issues/227) for more detail.\n\n## [Exercise 10.6](ex10_06.cpp)\n\n## [Exercise 10.7](ex10_07.cpp)\n\n## Exercise 10.8:\n>We said that algorithms do not change the size of the containers over which they operate. Why doesn’t the use of back_inserter invalidate this claim?\n\nInserters like `back_inserter` is part of `<iterator>` rather than `<algorithm>`. \n\n## [Exercise 10.9](ex10_09.cpp)\n\n## Exercise 10.10:\n>Why do you think the algorithms don’t change the size of containers?\n\n@Mooophy:\nThe aim of this design is to separate the algorithms and the operation provided by member function.\n\n@pezy:\nCause the library algorithms operate on **iterators**, **not containers**. Thus, an algorithm **cannot (directly)** add or remove elements.\n\n## [Exercise 10.11](ex10_11.cpp)\n## [Exercise 10.12](ex10_12.cpp)\n## [Exercise 10.13](ex10_13.cpp)\n\n## Exercise 10.14:\n>Write a lambda that takes two ints and returns their sum.\n\n```cpp\nauto add = [](int lhs, int rhs){ return lhs + rhs; };\n```\n\n## Exercise 10.15:\n>Write a lambda that captures an int from its enclosing function and takes an int parameter.\nThe lambda should return the sum of the captured int and the int parameter.\n\n```cpp\nint i = 42;\nauto add = [i](int num){ return i + num; };\n```\n\n## [Exercise 10.16](ex10_16.cpp)\n## [Exercise 10.17](ex10_17.cpp)\n## [Exercise 10.18 and 10.19](ex10_18_19.cpp)\n## [Exercise 10.20 and 10.21](ex10_20_21.cpp)\n## [Exercise 10.22](ex10_22.cpp)\n\n## Exercise 10.23:\n>How many arguments does bind take?\n\nAssuming the function to be bound have `n` parameters, bind take `n + 1` parameters.\nThe additional one is for the function to be bound itself.\n\n## [Exercise 10.24](ex10_24.cpp)\n## [Exercise 10.25](ex10_25.cpp)\n\n## Exercise 10.26:\n>Explain the differences among the three kinds of insert iterators.\n\n- `back_inserter` uses `push_back`.\n- `front_inserter` uses `push_front`.\n- `insert` uses `insert`\n>This function takes a second argument, which must be an iterator into the given container. Elements are inserted ahead of the element denoted by the given iterator.\n\n## [Exercise 10.27](ex10_27.cpp)\n## [Exercise 10.28](ex10_28.cpp)\n## [Exercise 10.29](ex10_29.cpp)\n## [Exercise 10.30](ex10_30.cpp)\n## [Exercise 10.31](ex10_31.cpp)\n## [Exercise 10.32](ex10_32.cpp)\n## [Exercise 10.33](ex10_33.cpp)\n## [Exercise 10.34 ~ 10.37](ex10_34_35_36_37.cpp)\n\n## Exercise 10.38:\n>List the five iterator categories and the operations that each supports.\n\n- Input iterators : `==`, `!=`, `++`, `*`, `->`\n- Output iterators : `++`, `*`\n- Forward iterators : `==`, `!=`, `++`, `*`, `->`\n- Bidirectional iterators : `==`, `!=`, `++`, `--`, `*`, `->`\n- Random-access iterators : `==`, `!=`, `<`, `<=`, `>`, `>=`, `++`, `--`, `+`, `+=`, `-`, `-=`, `-`(two iterators), `*`, `->`, `iter[n]` == `* (iter + n)`\n\n## Exercise 10.39:\n>What kind of iterator does a list have? What about a vector?\n\n`list` have the **Bidirectional iterators**.  `vector` have the **Random-access iterators**.\n\n## Exercise 10.40:\n>What kinds of iterators do you think copy requires? What about reverse or unique?\n\n- `copy` : first and second are Input iterators, last is Output iterators.\n- `reverse` : Bidirectional iterators.\n- `unique` : Forward iterators.\n\n## Exercise 10.41:\n>Based only on the algorithm and argument names, describe the operation that the each of the following library algorithms performs:\n```cpp\nreplace(beg, end, old_val, new_val); // replace the old_elements in the input range as new_elements.\nreplace_if(beg, end, pred, new_val); // replace the elements in the input range which pred is true as new_elements.\nreplace_copy(beg, end, dest, old_val, new_val); // copy the new_elements which is old_elements in the input range into dest.\nreplace_copy_if(beg, end, dest, pred, new_val); // copy the new_elements which pred is true in the input range into dest.\n```\n\n## [Exercise 10.42](ex10_42.cpp)\n"
  },
  {
    "path": "ch10/ex10_01_02.cpp",
    "content": "//\n// @author Yue Wang\n// @date   01.12.2014\n//\n// Exercise 10.1:\n// The algorithm header defines a function named count that, like find,\n// takes a pair of iterators and a value.count returns a count of how\n// often that value appears.\n// Read a sequence of ints into a vector and print the count of how many\n// elements have a given value.\n//\n// Exercise 10.2:\n// Repeat the previous program, but read values into a list of strings.\n//\n\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <list>\n\n\nint main()\n{\n    // 10.1\n    std::vector<int> v = { 1, 2, 3, 4, 5, 6, 6, 6, 2 };\n    std::cout << \"ex 10.01: \" << std::count(v.cbegin(), v.cend(), 6) << std::endl;\n\n    // 10.2\n    std::list<std::string> l = { \"aa\", \"aaa\", \"aa\", \"cc\" };\n    std::cout << \"ex 10.02: \" << std::count(l.cbegin(), l.cend(), \"aa\") << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_03_04.cpp",
    "content": "//\n// @author Yue Wang\n// @date   01.12.2014\n//\n// Exercise 10.3:\n// Use accumulate to sum the elements in a vector<int>.\n//\n// Exercise 10.4:\n// Assuming v is a vector<double>, what, if anything,\n// is wrong with calling accumulate(v.cbegin(), v.cend(), 0)?\n//  Check below.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nint main()\n{\n    // Exercise 10.3\n    std::vector<int> v = { 1, 2, 3, 4 };\n    std::cout << \"ex 10.03: \" << std::accumulate(v.cbegin(), v.cend(), 0) << std::endl;\n\n    // Exercise 10.4\n    std::vector<double> vd = { 1.1, 0.5, 3.3 };\n    std::cout   << \"ex 10.04: \"\n                << std::accumulate(vd.cbegin(), vd.cend(), 0)\n                << std::endl;                        //   ^<-- note here.\n    // @attention\n    //\n    // The ouput is 4 rather than 4.9 as expected.\n    // The reason is std::accumulate is a template function. The third parameter is _Tp __init\n    // When \"0\" , an integer, had been specified here, the compiler deduced _Tp as\n    // interger.As a result , when the following statments were being excuted :\n    //  for (; __first != __last; ++__first)\n    //\t__init = __init + *__first;\n    //  return __init;\n    // all calculation would be converted to integer.\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_06.cpp",
    "content": "//\n//  ex10_06.cpp\n//  Exercise 10.6\n//\n//  Created by pezy on 12/9/14.\n//\n//  @Brief  Using fill_n, write a program to set a sequence of int values to 0.\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n\nusing std::vector; using std::cout; using std::endl; using std::fill_n;\n\nint main()\n{\n    vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    fill_n(vec.begin(), vec.size(), 0);\n\n    for (auto i : vec)\n        cout << i << \" \";\n    cout << endl;\n}\n"
  },
  {
    "path": "ch10/ex10_07.cpp",
    "content": "//\n//  ex10_07.cpp\n//  Exercise 10.7\n//\n//  Created by pezy on 12/9/14.\n//\n//  @Brief  Determine if there are any errors in the following programs and, if so, correct the error(s)\n\n#include <iostream>\n#include <vector>\n#include <list>\n#include <algorithm>\n\nusing std::vector; using std::cout; using std::endl; using std::list; using std::cin; using std::fill_n;\n\ntemplate<typename Sequence>\nvoid print(Sequence const& seq)\n{\n    for (const auto& i : seq)\n        cout << i << \" \";\n    cout << endl;\n}\n\nint main()\n{\n    // (a)\n    vector<int> vec;\n    list<int> lst;\n    int i;\n    while (cin >> i)\n        lst.push_back(i);\n\n    copy(lst.cbegin(), lst.cend(), back_inserter(vec));\n    // Fixed: the vec.begin() was replaced by a back_inserter iterator, capable of\n    // insert new elements automatically at the end of the container.\n    \n    // (b)\n    vector<int> v;\n    v.reserve(10);\n    fill_n(v.begin(), 10, 0);\n    // ^ (b)No error, but not any sense. v.size() still equal zero.\n    // Fixed: 1. use `v.resize(10);`\n    //    or  2. use `fill_n(std::back_inserter(v), 10, 0)`\n    \n    print(v);\n    print(vec);\n}\n"
  },
  {
    "path": "ch10/ex10_09.cpp",
    "content": "//\n// @author @Yue Wang @shbling @pezy @zzzkl @Yue Wang\n// @date   01.12.2014  Jun 2015\n//\n// Exercise 10.9:\n// Implement your own version of elimDups. Test your program by printing\n// the vector after you read the input, after the call to unique, and after\n// the call to erase.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n\n// print containers like vector, deque, list, etc.\ntemplate<typename Sequence>\nauto println(Sequence const& seq) -> std::ostream&\n{\n    for (auto const& elem : seq) \n        std::cout << elem << \" \";\n    return std::cout << std::endl;\n}\n\nauto eliminate_duplicates(std::vector<std::string> &vs) -> std::vector<std::string>&\n{\n    std::sort(vs.begin(), vs.end());\n    println(vs);\n\n    auto new_end = std::unique(vs.begin(), vs.end());\n    println(vs);\n\n    vs.erase(new_end, vs.end());\n    return vs;\n}\n\nint main()\n{\n    std::vector<std::string> vs{ \"a\", \"v\", \"a\", \"s\", \"v\", \"a\", \"a\" };\n    println(vs);\n    println(eliminate_duplicates(vs));\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_11.cpp",
    "content": "// @Alan\n// Exercise 10.11:\n// Write a program that uses stable_sort and isShorter to sort a vector passed\n// to your version of elimDups.\n// Print the vector to verify that your program is correct.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <list>\n\n// print a container like vector, deque, list, etc.\ntemplate<typename Sequence>\ninline std::ostream& println(Sequence const& seq)\n{\n    for(auto const& elem : seq) std::cout << elem << \" \";\n    std::cout << std::endl;\n\n    return std::cout;\n}\n\n\ninline bool\nis_shorter(std::string const& lhs, std::string const& rhs)\n{\n    return  lhs.size() < rhs.size();\n}\n\n\nvoid elimdups(std::vector<std::string> &vs)\n{\n    std::sort(vs.begin(), vs.end());\n    auto new_end = std::unique(vs.begin(), vs.end());\n    vs.erase(new_end, vs.end());\n}\n\n\nint main()\n{\n    std::vector<std::string> v{\n        \"1234\", \"1234\", \"1234\", \"Hi\", \"alan\", \"wang\"\n    };\n    elimdups(v);\n    std::stable_sort(v.begin(), v.end(), is_shorter);\n    std::cout << \"ex10.11 :\\n\";\n    println(v);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_12.cpp",
    "content": "// @Yue Wang\n// Exercise 10.12:\n// Write a function named compareIsbn that compares the isbn() members of two Sales_data objects.\n// Use that function to sort a vector that holds Sales_data objects.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include \"../ch07/ex7_26.h\"     // Sales_data class.\n\ninline bool compareIsbn(const Sales_data &sd1, const Sales_data &sd2)\n{\n    return sd1.isbn().size() < sd2.isbn().size();\n}\n\nint main()\n{\n    Sales_data d1(\"aa\"), d2(\"aaaa\"), d3(\"aaa\"), d4(\"z\"), d5(\"aaaaz\");\n    std::vector<Sales_data> v{ d1, d2, d3, d4, d5 };\n\n    // @note   the elements the iterators pointing to\n    //         must match the parameters of the predicate.\n    std::sort(v.begin(), v.end(), compareIsbn);\n\n    for(const auto &element : v)\n        std::cout << element.isbn() << \" \";\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_13.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 10.13:\n// The library defines an algorithm named partition that takes a predicate\n// and partitions the container so that values for which the predicate is\n// true appear in the first part and those for which the predicate is false\n// appear in the second part. The algorithm returns an iterator just past\n// the last element for which the predicate returned true. Write a function\n// that takes a string and returns a bool indicating whether the string has\n// five characters or more. Use that function to partition words. Print the\n// elements that have five or more characters.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n\nbool predicate(const std::string &s) \n{ \n    return s.size() >= 5; \n}\n\nint main()\n{\n    auto v = std::vector<std::string>{ \"a\", \"as\", \"aasss\", \"aaaaassaa\", \"aaaaaabba\", \"aaa\" };\n    auto pivot = std::partition(v.begin(), v.end(), predicate);\n    \n    for (auto it = v.cbegin(); it != pivot; ++it)\n        std::cout << *it << \" \";\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_16.cpp",
    "content": "//\n// @author @Yue Wang @pezy\n// @date   02.12.2014\n//\n// Exercise 10.16:\n// Write your own version of the biggies function using lambdas.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n\n// from ex 10.9\nvoid elimdups(std::vector<std::string> &vs)\n{\n    std::sort(vs.begin(), vs.end());\n    auto new_end = std::unique(vs.begin(), vs.end());\n    vs.erase(new_end, vs.end());\n}\n\nvoid biggies(std::vector<std::string> &vs, std::size_t sz)\n{\n    using std::string;\n\n    elimdups(vs);\n\n    // sort by size, but maintain alphabetical order for same size.\n    std::stable_sort(vs.begin(), vs.end(), [](string const& lhs, string const& rhs){\n        return lhs.size() < rhs.size();\n    });\n\n    // get an iterator to the first one whose size() is >= sz\n    auto wc = std::find_if(vs.begin(), vs.end(), [sz](string const& s){\n            return s.size() >= sz;\n    });\n        \n    // print the biggies\n    std::for_each(wc, vs.end(), [](const string &s){\n        std::cout << s << \" \";\n    }); \n}\n\nint main()\n{\n    // ex10.16\n    std::vector<std::string> v\n    {\n        \"1234\",\"1234\",\"1234\",\"hi~\", \"alan\", \"alan\", \"cp\"\n    };\n    std::cout << \"ex10.16: \";\n    biggies(v, 3);\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_17.cpp",
    "content": "// @pezy\n//\n// Exercise 10.17\n// Rewrite exercise 10.12 from  10.3.1 (p. 387) \n// to use a lambda in the call to sort instead of the compareIsbn function. \n//\n// @See 7.26, 10.12\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include \"../ch07/ex7_26.h\"     // Sales_data class.\n\nint main()\n{\n    Sales_data d1(\"aa\"), d2(\"aaaa\"), d3(\"aaa\"), d4(\"z\"), d5(\"aaaaz\");\n    std::vector<Sales_data> v{ d1, d2, d3, d4, d5 };\n\n    std::sort(v.begin(), v.end(), [](const Sales_data &sd1, const Sales_data &sd2){\n        return sd1.isbn().size() < sd2.isbn().size();\n    });\n\n    for(const auto &element : v)\n        std::cout << element.isbn() << \" \";\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_18_19.cpp",
    "content": "//\n// @author @Yue Wang @pezy\n// @date   12.10.2014\n//\n// Exercise 10.18:\n// Rewrite biggies to use partition instead of find_if.\n//\n// Exercise 10.19:\n// Rewrite the previous exercise to use stable_partition, which like\n// stable_sort maintains the original element order in the paritioned\n// sequence.\n//\n\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n\n// from ex 10.9\nvoid elimdups(std::vector<std::string> &vs)\n{\n    std::sort(vs.begin(), vs.end());\n    auto new_end = std::unique(vs.begin(), vs.end());\n    vs.erase(new_end, vs.end());\n}\n\n\n// ex10.18\nvoid biggies_partition(std::vector<std::string> &vs, std::size_t sz)\n{\n    elimdups(vs);\n    \n    auto pivot = partition(vs.begin(), vs.end(), [sz](const std::string &s){\n        return s.size() >= sz;}\n    );\n\n    for(auto it = vs.cbegin(); it != pivot; ++it)\n        std::cout << *it << \" \";\n}\n\n\n// ex10.19\nvoid biggies_stable_partition(std::vector<std::string> &vs, std::size_t sz)\n{\n    elimdups(vs);\n    \n    auto pivot = stable_partition(vs.begin(), vs.end(), [sz](const std::string& s){\n        return s.size() >= sz;\n    });\n\n    for(auto it = vs.cbegin(); it != pivot; ++it)\n        std::cout << *it << \" \";\n}\n\n\nint main()\n{\n    // ex10.18\n    std::vector<std::string> v{\n        \"the\", \"quick\", \"red\", \"fox\", \"jumps\", \"over\", \"the\", \"slow\", \"red\", \"turtle\"\n    };\n    \n    std::cout << \"ex10.18: \";\n    std::vector<std::string> v1(v);\n    biggies_partition(v1, 4);\n    std::cout << std::endl;\n\n    // ex10.19\n    std::cout << \"ex10.19: \";\n    std::vector<std::string> v2(v);\n    biggies_stable_partition(v2, 4);\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_20_21.cpp",
    "content": "//\n// @author @Yue Wang @shbling @pezy @zzzkl @agyild\n// @date   04.01.2018\n//\n// Exercise 10.20:\n// The library defines an algorithm named count_if. Like find_if, this function takes\n// a pair of iterators denoting an input range and a predicate that it applies to each\n// element in the given range. count_if returns a count of how often the predicate is\n// true. Use count_if to rewrite the portion of our program that counted how many words\n// are greater than length 6.\n//\n// Exercise 10.21:\n// Write a lambda that captures a local int variable and decrements that variable until\n// it reaches 0. Once the variable is 0 additional calls should no longer decrement the\n// variable. The lambda should return a bool that indicates whether the captured variable is 0.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n\n\nusing std::vector;\nusing std::count_if;\nusing std::string;\n\n\n// Exercise 10.20\nstd::size_t bigerThan6(vector<string> const& v)\n{\n    return count_if(v.cbegin(), v.cend(), [](string const& s){\n        return s.size() > 6;\n    });\n}\n\n\nint main()\n{\n    // ex10.20\n    vector<string> v{\n        \"alan\",\"moophy\",\"1234567\",\"1234567\",\"1234567\",\"1234567\"\n    };\n    std::cout << \"ex10.20: \" << bigerThan6(v) << std::endl;\n\n    // ex10.21\n    int i = 7;\n    auto check_and_decrement = [&i]() { return i > 0 ? !--i : !i; };\n    std::cout << \"ex10.21: \";\n    while(!check_and_decrement())\n        std::cout << i << \" \";\n    std::cout << i << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_22.cpp",
    "content": "//\n//  ex10_22.cpp\n//  Exercise 10.22\n//\n//  Created by pezy on 12/11/14.\n//  Updated by pezy on 10/12/15.\n//\n//  @Brief  Rewrite the program to count words of size 6 or less using\n//          functions in place of the lambdas.\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <functional>\n\nusing std::string;\nusing namespace std::placeholders;\n\nbool isLesserThanOrEqualTo6(const string &s, string::size_type sz)\n{\n    return s.size() <= sz;\n}\n\nint main()\n{\n    std::vector<string> authors{ \"Mooophy\", \"pezy\", \"Queequeg90\", \"shbling\", \"evan617\" };\n    std::cout << count_if(authors.cbegin(), authors.cend(), bind(isLesserThanOrEqualTo6, _1, 6));\n}\n"
  },
  {
    "path": "ch10/ex10_24.cpp",
    "content": "//\n// @author @Yue Wang @shbling @Soyn @Yue Wang\n//\n// Exercise 10.24:\n// Use bind and check_size to find the first element in a vector of ints that has a value greater\n// than the length of a specified string value.\n//\n//  Discussion over this exercise on StackOverflow\n//  http://stackoverflow.com/questions/20539406/what-type-does-stdfind-if-not-return\n//\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <functional>\n\n\nusing std::cout;\nusing std::endl;\nusing std::string;\nusing std::vector;\nusing std::find_if;\nusing std::bind;\nusing std::size_t;\n\nauto check_size(string const& str, size_t sz)\n{\n    return str.size() < sz;\n}\n\nint main()\n{\n    vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7 };\n    string str(\"123456\");\n    auto result = find_if(vec.begin(), vec.end(), bind(check_size, str, std::placeholders::_1));\n    if (result != vec.end())\n        cout << *result << endl;\n    else\n        cout << \"Not found\" << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_25.cpp",
    "content": "//\n//  ex10_25.cpp\n//  Exercise 10.25\n//\n//  Created by pezy on 12/11/14.\n//\n//  @Brief  In the exercises for 10.3.2 (p.392) you wrote a version of biggies that uses partition.\n//          Rewrite that function to use check_size and bind.\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <functional>\n\nusing std::string; using std::vector;\nusing namespace std::placeholders;\n\nvoid elimdups(vector<string> &vs)\n{\n    std::sort(vs.begin(), vs.end());\n    vs.erase(unique(vs.begin(), vs.end()), vs.end());\n}\n\nbool check_size(const string &s, string::size_type sz)\n{\n    return s.size() >= sz;\n}\n\nvoid biggies(vector<string> &words, vector<string>::size_type sz)\n{\n    elimdups(words);\n    auto iter = std::stable_partition(words.begin(), words.end(), bind(check_size, _1, sz));\n    for_each(words.begin(), iter, [](const string &s){ std::cout << s << \" \"; });\n}\n\nint main()\n{\n    std::vector<std::string> v{\n        \"the\", \"quick\", \"red\", \"fox\", \"jumps\", \"over\", \"the\", \"slow\", \"red\", \"turtle\"\n    };\n    biggies(v, 4);\n}\n"
  },
  {
    "path": "ch10/ex10_27.cpp",
    "content": "//\n//  ex10_27.cpp\n//  Exercise 10.27\n//\n//  Created by pezy on 12/13/14.\n//\n//  In addition to unique, the library defines function named unique_copy that\n//  takes a third iterator denoting a destination into which to copy the unique elements.\n//  Write a program that uses unique_copy to copy the unique elements from\n//  a vector into an initially empty list.\n\n#include <iostream>\n#include <algorithm>\n#include <vector>\n#include <list>\n#include <iterator>\n\nint main()\n{\n    std::vector<int> vec{ 1, 1, 3, 3, 5, 5, 7, 7, 9 };\n    std::list<int> lst;\n    \n    std::unique_copy(vec.begin(), vec.end(), back_inserter(lst));\n    for (auto i : lst)\n        std::cout << i << \" \";\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch10/ex10_28.cpp",
    "content": "//\n//  ex10_28.cpp\n//  Exercise 10.28\n//\n//  Created by pezy on 12/13/14.\n//\n//  Copy a vector that holds the values from 1 to 9 inclusive, into three other containers.\n//  Use an inserter, a back_inserter, and a front_inserter, respectivly to add elements to these containers.\n//  Predict how the output sequence varies by the kind of inserter and verify your predictions\n//  by running your programs.\n\n\n#include <iostream>\n#include <algorithm>\n#include <vector>\n#include <list>\n#include <iterator>\nusing std::list; using std::copy; using std::cout; using std::endl;\n\ntemplate<typename Sequence>\nvoid print(Sequence const& seq)\n{\n    for (const auto& i : seq)\n        std::cout << i << \" \";\n    std::cout << std::endl;\n}\n\nint main()\n{\n    std::vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    \n    // uses inserter\n    list<int> lst1;\n    copy(vec.cbegin(), vec.cend(), inserter(lst1, lst1.begin()));\n    print(lst1);\n    \n    // uses back_inserter\n    list<int> lit2;\n    copy(vec.cbegin(), vec.cend(), back_inserter(lit2));\n    print(lit2);\n    \n    // uses front_inserter\n    list<int> lst3;\n    copy(vec.cbegin(), vec.cend(), front_inserter(lst3));\n    print(lst3);\n}\n"
  },
  {
    "path": "ch10/ex10_29.cpp",
    "content": "//\n//  ex10_29.cpp\n//  Exercise 10.29\n//\n//  Created by pezy on 12/13/14.\n//\n//  Write a program using stream iterators to read a text file into a vector of strings.\n\n\n#include <iostream>\n#include <fstream>\n#include <vector>\n#include <string>\n#include <iterator>\n\nusing std::string;\n\nint main()\n{\n    std::ifstream ifs(\"../data/book.txt\");\n    std::istream_iterator<string> in(ifs), eof;\n    std::vector<string> vec;\n    std::copy(in, eof, back_inserter(vec));\n    \n    // output\n    std::copy(vec.cbegin(), vec.cend(), std::ostream_iterator<string>(std::cout, \"\\n\"));\n}\n"
  },
  {
    "path": "ch10/ex10_30.cpp",
    "content": "//\n//  ex10_30.cpp\n//  Exercise 10.30\n//\n//  Created by pezy on 12/13/14.\n//\n//  Use stream iterators, sort, and copy to read a sequence of integers from the standard input,\n//  sort them, and then write them back to the standard output.\n\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <iterator>\n\nint main()\n{\n    std::vector<int> vec(std::istream_iterator<int>(std::cin), std::istream_iterator<int>());\n    std::sort(vec.begin(), vec.end());\n    std::copy(vec.cbegin(), vec.cend(), std::ostream_iterator<int>(std::cout, \" \"));\n}\n"
  },
  {
    "path": "ch10/ex10_31.cpp",
    "content": "//\n//  ex10_31.cpp\n//  Exercise 10.31\n//\n//  Created by pezy on 12/13/14.\n//\n//  Update the program from the previous exercise so that it prints only the unique elements.\n//  Your program should use unqiue_copy\n\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <iterator>\n\nint main()\n{\n    std::istream_iterator<int> in_iter(std::cin), eof;\n    std::vector<int> vec;\n    while (in_iter != eof)\n        vec.push_back(*in_iter++);\n    std::sort(vec.begin(), vec.end());\n    std::unique_copy(vec.cbegin(), vec.cend(), std::ostream_iterator<int>(std::cout, \" \"));\n}\n"
  },
  {
    "path": "ch10/ex10_32.cpp",
    "content": "//\n//  ex10_32.cpp\n//  Exercise 10.32\n//\n//  Created by pezy on 12/13/14.\n//\n//  Rewrite the bookstore problem from 1.6 (p. 24) using a vector to hold the transactions\n//  and various algorithms to do the processing.\n//  Use sort with your compareIsbn function from 10.3.1 (p. 387) to arrange the transactions in order,\n//  and then use find and accumulate to do the sum.\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <iterator>\n#include <numeric>\n#include \"../include/Sales_item.h\"\n\nbool compareIsbn(const Sales_item &item1, const Sales_item &item2) {\n    return item1.isbn() < item2.isbn();\n}\n\nint main()\n{\n    std::istream_iterator<Sales_item> in_iter(std::cin), in_eof;\n    std::vector<Sales_item> vec;\n    \n    while (in_iter != in_eof)\n        vec.push_back(*in_iter++);\n    sort(vec.begin(), vec.end(), compareIsbn);\n    for (auto beg = vec.cbegin(), end = beg; beg != vec.cend(); beg = end) {\n        end = find_if(beg, vec.cend(), [beg](const Sales_item &item){ return item.isbn() != beg->isbn(); });\n        std::cout << std::accumulate(beg, end, Sales_item(beg->isbn())) << std::endl;\n    }\n}\n"
  },
  {
    "path": "ch10/ex10_33.cpp",
    "content": "//\n//  ex10_33.cpp\n//  Exercise 10.33\n//\n//  Created by pezy on 12/13/14.\n//\n//  Write a program that takes the names of an input file and two output files.\n//  The input file should hold integers. Using an istream_iterator read the input file.\n//  Using ostream_iterators, write the odd numbers into the first output file.\n//  Each value should be followed by a space.Write the even numbers into the second file.\n//  Each of these values should be placed on a separate line.\n//\n//  Run: ./a.out \"../data/input.txt\" \"../data/odd.txt\" \"../data/even.txt\"\n\n#include <fstream>\n#include <iterator>\n#include <algorithm>\n\nint main(int argc, char **argv)\n{\n    if (argc != 4) return -1;\n\n    std::ifstream ifs(argv[1]);\n    std::ofstream ofs_odd(argv[2]), ofs_even(argv[3]);\n\n    std::istream_iterator<int> in(ifs), in_eof;\n    std::ostream_iterator<int> out_odd(ofs_odd, \" \"), out_even(ofs_even, \"\\n\");\n\n    std::for_each(in, in_eof, [&out_odd, &out_even](const int i){\n        *(i & 0x1 ? out_odd : out_even)++ = i;\n    });\n\n    return 0;\n}\n"
  },
  {
    "path": "ch10/ex10_34_35_36_37.cpp",
    "content": "// @Alan @pezy\n//\n// Exercise 10.34:\n// Use reverse_iterators to print a vector in reverse order.\n//\n// Exercise 10.35:\n// Now print the elements in reverse order using ordinary iterators.\n//\n// Exercise 10.36:\n// Use find to find the last element in a list of ints with value 0.\n//\n// Exercise 10.37:\n// Given a vector that has ten elements, copy the elements from positions\n// 3 through 7 in reverse order to a list.\n//\n\n#include <iostream>\n#include <algorithm>\n#include <list>\n#include <vector>\n#include <iterator>\n\nint main()\n{\n    std::vector<int> vec = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\n    // 10.34\n    for (auto rit = vec.crbegin(); rit != vec.crend(); ++rit)\n        std::cout << *rit << \" \";\n    std::cout << std::endl;\n\n    // 10.35\n    for (auto it = std::prev(vec.cend()); true; --it) {\n        std::cout << *it << \" \";\n        if (it == vec.cbegin()) break;\n    }\n    std::cout << std::endl;\n\n    // 10.36\n    std::list<int> lst = { 1, 2, 3, 4, 0, 5, 6 };\n    auto found_0 = std::find(lst.crbegin(), lst.crend(), 0);\n    std::cout << std::distance(found_0, lst.crend()) << std::endl;\n\n    // 10.37\n    std::list<int> ret_lst(8 - 3);\n    std::copy(vec.cbegin() + 3, vec.cbegin() + 8, ret_lst.rbegin());\n    //     0, 1, 2, 3, 4, 5, 6, 7, 8, 9\n    //           ^              ^\n    //          rend          rbegin\n    // @note: std::copy copies the range [first, last) into result.\n    //        hence, the arguments here denote:\n    //        [7 6 5 4 3 2)\n    //                   ^ this one is specified but not included.\n    for (auto i : ret_lst) std::cout << i << \" \";\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch10/ex10_42.cpp",
    "content": "// @Alan @pezy\n//\n// Exercise 10.42:\n// Reimplement the program that eliminated duplicate words that\n// we wrote in § 10.2.3 (p. 383) to use a list instead of a vector.\n//\n\n#include <iostream>\n#include <string>\n#include <list>\n\nusing std::string; using std::list;\n\nvoid elimDups(list<string> &words)\n{\n    words.sort();\n    words.unique();\n}\n\nint main()\n{\n    list<string> l = { \"aa\", \"aa\", \"aa\", \"aa\", \"aasss\", \"aa\" };\n    elimDups(l);\n    for (const auto& e : l)\n        std::cout << e << \" \";\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch11/README.md",
    "content": "# Chapter 11. Associative Containers\n\n## Exercise 11.1:\n>Describe the differences between a map and a vector.\n\n`map` is an associative container whereas `vector` is a sequence container\n\n## Exercise 11.2:\n>Give an example of when each of list, vector, deque, map, and set might be most useful.\n\n- list : anytime when a doubly-linked list is required.\n- vector : anytime when a dynamic array is required.\n- deque : [An answer from SO](http://stackoverflow.com/questions/3880254/why-do-we-need-deque-data-structures-in-the-real-world).\n- map : dictionary.\n- set : when to keep elements sorted and unique.\n\n## [Exercise 11.3 and 11.4](ex11_3_4.cpp)\n\n## Exercise 11.5:\n>Explain the difference between a map and a set. When might you use one or the other?\n\n[A nice answer on SO](http://stackoverflow.com/questions/16286714/advantages-of-stdset-vs-vectors-or-maps)\n\n## Exercise 11.6:\n>Explain the difference between a set and a list. When might you use one or the other?\n\n[list vs set](http://stackoverflow.com/questions/2302681/c-stl-list-vs-set)\n\n## [Exercise 11.7](ex11_7.cpp)\n## [Exercise 11.8](ex11_8.cpp)\n## [Exercise 11.9 and 11.10](ex11_9_10.cpp)\n## [Exercise 11.11](ex11_11.cpp)\n## [Exercise 11.12 and 11.13](ex11_12_13.cpp)\n## [Exercise 11.14](ex11_14.cpp)\n\n## Exercise 11.15:\n>What are the mapped_type, key_type, and value_type of a map from int to vector< int >?\n\n- mapped_type : vector< int >\n- key_type : int\n- value_type : std::pair< const int, vector<int> >\n\n## Exercise 11.16:\n>Using a map iterator write an expression that assigns a value to an element.\n\n```cpp\nstd::map<int, std::string> map;\nmap[25] = \"Alan\";\nstd::map<int, std::string>::iterator it = map.begin();\nit->second = \"Wang\";\n```\n\n## Exercise 11.17:\n>Assuming c is a multiset of strings and v is a vector\nof strings, explain the following calls. Indicate whether each call is legal:\n\n```cpp\ncopy(v.begin(), v.end(), inserter(c, c.end())); // legal\ncopy(v.begin(), v.end(), back_inserter(c)); // illegal, no `push_back` in `set`.\ncopy(c.begin(), c.end(), inserter(v, v.end())); // legal.\ncopy(c.begin(), c.end(), back_inserter(v)); // legal.\n```\n## Exercise 11.18:\n>Write the type of map_it from the loop on page 430 without using auto or decltype.\n\n```cpp\nstd::map<std::string, size_t>::const_iterator;\n```\n## Exercise 11.19:\n>Define a variable that you initialize by calling begin() on the multiset named bookstore from 11.2.2 (p. 425).\nWrite the variable’s type without using auto or decltype.\n\n```cpp\nusing compareType = bool (*)(const Sales_data &lhs, const Sales_data &rhs);\nstd::multiset<Sales_data, compareType> bookstore(compareIsbn);\nstd::multiset<Sales_data, compareType>::iterator c_it = bookstore.begin();\n```\n## [Exercise 11.20](ex11_20.cpp)\n## Exercise 11.21:\n>Assuming word_count is a map from string to size_t and word is a string, explain the following loop:\n\n```cpp\nwhile (cin >> word)\n    ++word_count.insert({ word, 0 }).first->second;\n```\nThis code can be explained like this pseudocode:\n```python\nwhile reading into word\n    if word_count has key word:\n        word_count[word] += 1\n    else:\n        word_count[word] = 0\n        word_count[word] += 1\n```\n\n## Exercise 11.22:\n>Given a `map<string, vector<int>>`, write the types used as an argument and as the return value for the version of insert that inserts one element.\n\n```cpp\nstd::pair<std::string, std::vector<int>>    // argument\nstd::pair<std::map<std::string, std::vector<int>>::iterator, bool> // return\n```\n\n## [Exercise 11.23](ex11_23.cpp)\n## [Exercise 11.24 ~ 11.26](ex11_24_25_26.cpp)\n## [Exercise 11.27 ~ 11.30](ex11_27_28_29_30.cpp)\n## [Exercise 11.31](ex11_31.cpp)\n## [Exercise 11.32](ex11_32.cpp)\n## [Exercise 11.33](ex11_33.cpp)\n\n## Exercise 11.34:\n>What would happen if we used the subscript operator instead of find in the transform function?\n\nSay the code has been changed like below:\n```cpp\nconst string& transform(const string &s, const map<string, string> &m)\n{\n    return m[s];\n}\n```\nThe above code won't compile because the subscript operator might insert an element (when the element with the key s is not found), and we may use subscript only on a map that is not const.\n\n## Exercise 11.35:\n>In buildMap, what effect, if any, would there be from rewriting `trans_map[key] = value.substr(1);` as `trans_map.insert({ key, value.substr(1) })`?\n\n- use subscript operator: if a word does appear multiple times, our loops will put the **last** corresponding phrase into trans_map\n- use `insert`: if a word does appear multiple times, our loops will put the **first** corresponding phrase into trans_map\n\n## Exercise 11.36:\n>Our program does no checking on the validity of either input file. In particular, it assumes that the rules in the transformation file are all sensible.\nWhat would happen if a line in that file has a key, one space, and then the end of the line? Predict the behavior and then check it against your version of the program.\n\nIf so, a key-value pair will be `{key, \" \"}`(\" \".size() !> 1), which cannot be added into the map. As a result, the key would not be replaced with any string.\n\n## Exercise 11.37:\n>What are the advantages of an unordered container as compared to the ordered version of that container? What are the advantages of the ordered version?\n\n[A summary](http://www.cs.fsu.edu/~lacher/courses/COP4531/fall13/lectures/containers2/slide04.html)\n\n## [Exercise 11.38](ex11_38.cpp)\n"
  },
  {
    "path": "ch11/ex11_11.cpp",
    "content": "//\n//  ex11_11.cpp\n//  Exercise 11.11\n//\n//  Created by pezy on 12/15/14.\n//  Refactored by Yue Wang Oct,2015\n//\n//  Redefine bookstore without using decltype.\n//\n\n#include \"../ch07/ex7_26.h\"\n#include <set>\n\nauto less(Sales_data const& lhs, Sales_data const& rhs)\n{\n    return lhs.isbn() < rhs.isbn();\n}\n\nint main()\n{\n    using Less = bool (*)(Sales_data const&, Sales_data const&);\n    std::multiset<Sales_data, Less> bookstore(less);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch11/ex11_12_13.cpp",
    "content": "//\n//  ex11_12_13.cpp\n//  Exercise 11.12 11.13\n//\n//  Created by pezy on 12/15/14.\n//\n//  Write a program to read a sequence of strings and ints,\n//  storing each into a pair. Store the pairs in a vector.\n//\n//  There are at least three ways to create the pairs in the program for the previous exercise.\n//  Write three versions of that program, creating the pairs in each way.\n//  Explain which form you think is easiest to write and understand, and why.\n\n#include <vector>\n#include <utility>\n#include <string>\n#include <iostream>\n\nint main()\n{\n    std::vector<std::pair<std::string, int>> vec;\n    std::string str;\n    int i;\n    while (std::cin >> str >> i)\n        vec.push_back(std::pair<std::string, int>(str, i));\n        //vec.push_back(std::make_pair(str, i));\n        //vec.push_back({ str, i });\n        //vec.emplace_back(str, i); //!! easiest way.\n    \n    for (const auto &p : vec)\n        std::cout << p.first << \":\" << p.second << std::endl;\n}\n"
  },
  {
    "path": "ch11/ex11_14.cpp",
    "content": "//\n// @Yue Wang\n//\n// Exercise 11.14:\n// Extend the map of children to their family name that you wrote for the\n// exercises in § 11.2.1 (p. 424) by having the vector store a pair that\n// holds a child’s name and birthday.\n//\n// Exercise 11.7:\n// Define a map for which the key is the family’s last name and\n// the value is a vector of the children’s names. Write code to\n// add new families and to add new children to an existing family.\n//\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <vector>\n\nusing std::ostream;\nusing std::cout;\nusing std::cin;\nusing std::endl;\nusing std::string;\nusing std::make_pair;\nusing std::pair;\nusing std::vector;\nusing std::map;\n\nclass Families\n{\npublic:\n    using Child     = pair<string, string>;\n    using Children  = vector<Child>;\n    using Data      = map<string, Children>;\n\n    auto add(string const& last_name, string const& first_name, string birthday)\n    {\n        auto child = make_pair(first_name, birthday);\n        _data[last_name].push_back(child);\n    }\n\n    auto print() const\n    {\n        for (auto const& pair : _data)\n        {\n            cout << pair.first << \":\\n\" ;\n            for (auto const& child : pair.second)\n                cout << child.first << \" \" << child.second << endl;\n            cout << endl;\n        }\n    }\n\nprivate:\n    Data _data;\n};\n\nint main()\n{\n    Families families;\n    auto msg = \"Please enter last name, first name and birthday:\\n\";\n    for (string l, f, b; cout << msg, cin >> l >> f >> b; families.add(l, f, b));\n    families.print();\n\n    return 0;\n}\n"
  },
  {
    "path": "ch11/ex11_20.cpp",
    "content": "// @Yue Wang @pezy\n//\n// Exercise 11.20:\n// Rewrite the word-counting program from § 11.1 (p. 421) to use insert instead\n// of subscripting. Which program do you think is easier to write and read?\n// Explain your reasoning.\n//\n\n#include <iostream>\n#include <map>\n#include <string>\n\nusing std::string;\nusing std::map;\nusing std::cin;\nusing std::cout;\n\nint main()\n{\n    map<string, size_t> counts;\n    for(string word; cin >> word;)\n    {\n        auto result = counts.insert({ word, 1 });\n        if(!result.second)\n            ++result.first->second;\n    }\n    for(auto const& count : counts)\n        cout << count.first << \" \" << count.second << ((count.second > 1) ? \" times\\n\" : \" time\\n\");\n}\n"
  },
  {
    "path": "ch11/ex11_23.cpp",
    "content": "//\n//  ex11_23.cpp\n//  Exercise 11.23\n//\n//  Created by pezy on 12/16/14.\n//\n//  Rewrite the map that stored vectors of children’s names with a key that is the family last name for the exercises\n//  in 11.2.1 (p. 424) to use a multimap.\n\n#include <map>\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::multimap;\nusing std::cin;\nusing std::endl;\n\nint main()\n{\n    multimap<string, string> families;\n    for (string lname, cname; cin >> cname >> lname; families.emplace(lname, cname));\n    for (auto const& family : families)\n        std::cout << family.second << \" \" << family.first << endl;\n}\n"
  },
  {
    "path": "ch11/ex11_24_25_26.cpp",
    "content": "// @Yue Wang\n//\n// Exercise 11.24:\n// What does the following program do?\n//     map<int, int> m;\n//     m[0] = 1;\n//  add a key-value pair { 0, 1 } into the map.\n//\n// Exercise 11.25:\n// Contrast the following program with the one in the previous exercise\n//     vector<int> v;\n//     v[0] = 1;\n//  UB, since it's trying to dereference an item out of range.\n//\n// Exercise 11.26:\n// What type can be used to subscript a map? What type does the subscript\n// operator return? Give a concrete example—that is, define a map and then\n// write the types that can be used to subscript the map and the type that\n// would be returned from the subscript operator.\n//\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <typeinfo>\n\nint main()\n{\n    // ex11.26\n    std::map<int, std::string> m = { { 1,\"ss\" },{ 2,\"sz\" } };\n    using KeyType = std::map<int, std::string>::key_type;\n\n    std::cout << \"type to subscript: \" << typeid(KeyType).name() << std::endl;\n    std::cout << \"returned from the subscript operator: \" << typeid(decltype(m[1])).name() << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch11/ex11_27_28_29_30.cpp",
    "content": "//\n// @Yue Wang\n//\n// Exercise 11.27:\n// What kinds of problems would you use count to solve?\n// When might you use find instead?\n//  I would use count to deal with multimap or multi multiset.\n//  As for the associative container that have unique key, I would use find instead of count.\n//\n// Exercise 11.28:\n// Define and initialize a variable to hold the result of\n// calling find on a map from string to vector of int.\n//\n// Exercise 11.29:\n// What do upper_bound, lower_bound, and equal_range return\n// when you pass them a key that is not in the container?\n//  If the element is not in the multimap, then lower_bound\n//  and upper_bound will return equal iterators; both will\n//  refer to the point at which the key can be inserted without\n//  disrupting the order.\n//\n//  If no matching element is found, then both the first and\n//  second iterators refer to the position where this key can\n//  be inserted.\n//\n// Exercise 11.30:\n// Explain the meaning of the operand pos.first->second used\n// in the output expression of the final program in this section.\n//     cout << pos.first->second << endl;\n//              ^^^^^^^^^^^^^^^^^\n//  pos                     a pair\n//  pos.first               the iterator refering to the first element with the matching key\n//  pos.first->second       the value part of the key-value of the first element with the matching key\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <algorithm>\n#include <vector>\n\nint main()\n{\n    std::map<std::string, std::vector<int>> m{ { \"Alan\",{ 1,2,3,4,5, } },{ \"John\",{ 1,5,6,7,8 } } };\n    // ex11.28\n    std::map<std::string, std::vector<int>>::iterator it = m.find(\"Alan\");\n    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n    return 0;\n}\n"
  },
  {
    "path": "ch11/ex11_31.cpp",
    "content": "//\n//  ex11_31.cpp\n//  Exercise 11.31\n//\n//  Created by pezy on 12/17/14.\n//\n//  Write a program that defines a multimap of authors and their works.\n//  Use **find** to find **an element** in the multimap and erase that element.\n//  Be sure your program works correctly if the element you look for is not in the map.\n\n#include <map>\n#include <string>\n#include <iostream>\n\nusing std::string;\n\nint main()\n{\n    std::multimap<string, string> authors{\n        { \"alan\", \"DMA\" },\n        { \"pezy\", \"LeetCode\" },\n        { \"alan\", \"CLRS\" },\n        { \"wang\", \"FTP\" },\n        { \"pezy\", \"CP5\" },\n        { \"wang\", \"CPP-Concurrency\" }\n    };\n    // want to delete an element that author is [Alan], work is [112].\n    string author = \"pezy\";\n    string work = \"CP5\";\n    \n    auto found = authors.find(author);\n    auto count = authors.count(author);\n    while (count) {\n        if (found->second == work) {\n            authors.erase(found);\n            break;   \n        }\n        ++found;\n        --count;\n    }\n    \n    for (const auto &author : authors)\n        std::cout << author.first << \" \" << author.second << std::endl;\n}\n"
  },
  {
    "path": "ch11/ex11_32.cpp",
    "content": "//\n//  ex11_32.cpp\n//  Exercise 11.32\n//\n//  Created by pezy on 12/17/14.\n//\n//  Using the multimap from the previous exercise, write a program to print the list of **authors and their works** alphabetically.\n\n#include <map>\n#include <set>\n#include <string>\n#include <iostream>\n\nusing std::string;\n\nint main()\n{\n    std::multimap<string, string> authors{\n        { \"alan\", \"DMA\" },\n        { \"pezy\", \"LeetCode\" },\n        { \"alan\", \"CLRS\" },\n        { \"wang\", \"FTP\" },\n        { \"pezy\", \"CP5\" },\n        { \"wang\", \"CPP-Concurrency\" }\n    };\n    std::map<string, std::multiset<string>> order_authors;\n    for (const auto &author : authors)\n        order_authors[author.first].insert(author.second);\n    for (const auto &author : order_authors) {\n        std::cout << author.first << \": \";\n        for (const auto &work : author.second)\n            std::cout << work << \" \";\n        std::cout << std::endl;\n    }\n}\n"
  },
  {
    "path": "ch11/ex11_33.cpp",
    "content": "//\n//  ex11_33.cpp\n//  Exercise 11.33\n//\n//  Created by pezy on 12/18/14.\n//\n//  Implement your own version of the word-transformation program.\n\n#include <map>\n#include <string>\n#include <fstream> \n#include <iostream>\n#include <sstream>\n\nusing std::string; using std::ifstream;\n\nstd::map<string, string> buildMap(ifstream &map_file)\n{\n    std::map<string, string> trans_map;\n    for (string key, value; map_file >> key && getline(map_file, value); )\n        if (value.size() > 1) trans_map[key] = value.substr(1).substr(0, value.find_last_not_of(' '));\n    return trans_map;\n}\n\nconst string & transform(const string &s, const std::map<string, string> &m)\n{\n    auto map_it = m.find(s);\n    return map_it == m.cend() ? s : map_it->second;\n}\n\nvoid word_transform(ifstream &map, ifstream &input)\n{\n    auto trans_map = buildMap(map);\n    for (string text; getline(input, text); ) {\n        std::istringstream iss(text);\n        for (string word; iss >> word; )\n            std::cout << transform(word, trans_map) << \" \";\n        std::cout << std::endl;\n    }\n}\n\nint main()\n{\n    ifstream ifs_map(\"../data/word_transformation_bad.txt\"), ifs_content(\"../data/given_to_transform.txt\");\n    if (ifs_map && ifs_content) word_transform(ifs_map, ifs_content);\n    else std::cerr << \"can't find the documents.\" << std::endl;\n}\n"
  },
  {
    "path": "ch11/ex11_38.cpp",
    "content": "//\n//  ex11_38.cpp\n//  Exercise 11.38\n//\n//  Created by pezy on 12/18/14.\n//\n//  Rewrite the word-counting (11.1, p. 421) and word-transformation (11.3.6, p. 440) programs to use an unordered_map.\n\n#include <unordered_map>\n#include <set>\n#include <string>\n#include <iostream>\n#include <fstream>\n#include <sstream>\n\nusing std::string;\n\nvoid wordCounting()\n{\n    std::unordered_map<string, size_t> word_count;\n    for (string word; std::cin >> word; ++word_count[word]);\n    for (const auto &w : word_count)\n        std::cout << w.first << \" occurs \" << w.second << (w.second > 1 ? \"times\" : \"time\") << std::endl;\n}\n\nvoid wordTransformation()\n{\n    std::ifstream ifs_map(\"../data/word_transformation.txt\"), ifs_content(\"../data/given_to_transform.txt\");\n    if (!ifs_map || !ifs_content) {\n        std::cerr << \"can't find the documents.\" << std::endl;\n        return;\n    }\n    \n    std::unordered_map<string, string> trans_map;\n    for (string key, value; ifs_map >> key && getline(ifs_map, value); )\n        if (value.size() > 1) trans_map[key] = value.substr(1).substr(0, value.find_last_not_of(' '));\n    \n    for (string text, word; getline(ifs_content, text); std::cout << std::endl)\n        for (std::istringstream iss(text); iss >> word; ) {\n            auto map_it = trans_map.find(word);\n            std::cout << (map_it == trans_map.cend() ? word : map_it->second) << \" \";\n        }\n}\n\nint main()\n{\n    //wordCounting();\n    wordTransformation();\n}\n"
  },
  {
    "path": "ch11/ex11_3_4.cpp",
    "content": "// @Yue Wang Aug, 2015\n//\n// Exercise 11.3:\n// Write your own version of the word-counting program.\n//\n// Exercise 11.4:\n// Extend your program to ignore case and punctuation.\n// For example, “example.” “example, ” and “Example” should\n// all increment the same counter.\n//\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <algorithm>\n#include <cctype>\n\nusing std::string;\nusing std::cin;\nusing std::cout;\nusing std::remove_if;\nusing Map = std::map<std::string, std::size_t>;\n\n//for ex11.3\nauto count()\n{\n    Map counts;\n    for (string w; cin >> w; ++counts[w]);\n    return counts;\n}\n\n//for ex11.4\nauto strip(string& str) -> string const&\n{\n    for (auto& ch : str) ch = tolower(ch);\n    str.erase(remove_if(str.begin(), str.end(), ispunct), str.end());\n    return str;\n}\n\n//for ex11.4\nauto strip_and_count()\n{\n    Map counts;\n    for (string w; cin >> w; ++counts[strip(w)]);\n    return counts;\n}\n\nauto print(Map const& m)\n{\n    for (auto const& kv : m)\n        cout << kv.first << \" : \" << kv.second << \"\\n\";\n}\n\nint main()\n{\n    cout << \"[ex11.3] Enter a few words please:\\n\";\n    print(count());\n    cin.clear();\n    cout << \"[ex11.4] Enter a few words please:\\n\";\n    print(strip_and_count());\n\n    return 0;\n}\n"
  },
  {
    "path": "ch11/ex11_7.cpp",
    "content": "// Yue Wang Oct, 2015\n//\n// Exercise 11.7:\n// Define a map for which the key is the family’s last name and\n// the value is a vector of the children’s names. Write code to\n// add new families and to add new children to an existing family.\n//\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <algorithm>\n#include <vector>\n\nusing std::string;\nusing std::vector;\nusing std::map;\nusing std::cin;\nusing std::cout;\nusing Families = map<string, vector<string>>;\n\nauto make_families()\n{\n    Families families;\n    for (string ln; cout << \"Last name:\\n\", cin >> ln && ln != \"@q\";)\n        for (string cn; cout << \"|-Children's names:\\n\", cin >> cn && cn != \"@q\";)\n            families[ln].push_back(cn);\n    return families;\n}\n\nauto print(Families const& families)\n{\n    for (auto const& family : families)\n    {\n        cout << family.first << \":\\n\";\n        for (auto const& child : family.second)\n            cout << child << \" \";\n        cout << \"\\n\";\n    }\n}\n\nint main()\n{\n    print(make_families());\n    return 0;\n}\n"
  },
  {
    "path": "ch11/ex11_8.cpp",
    "content": "// @Yue Wang Sep, 2015\n//\n// Exercise 11.8:\n// Write a program that stores the excluded words in a vector\n// instead of in a set. What are the advantages to using a set?\n//  copied from the post on stack overflow:\n//  1.No matter what elements you add or remove (unless you add\n//  a duplicate, which is not allowed in a set), it will always\n//  be ordered.\n//  2.A vector has exactly and only the ordering you explicitly\n//  give it. Items in a vector are where you put them. If you put\n//  them in out of order, then they're out of order; you now need\n//  to sort the container to put them back in order.\n//  3.However, if you are constantly inserting and removing items\n//  from the container, vector will run into many issues.\n//  4.The time it takes to insert an item into a vector is proportional\n//  to the number of items already in the vector. The time it takes\n//  to insert an item into a set is proportional to the log of the\n//  number of items. If the number of items is large, that's a huge\n//  difference. Log(100, 000) is 17; that's a major speed improvement.\n//  The same goes for removal.\n//\n//  http://stackoverflow.com/questions/8686725/what-is-the-difference-between-stdset-and-stdvector\n//\n#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n\nint main()\n{\n    std::vector<std::string> exclude = { \"aa\", \"bb\", \"cc\", \"dd\", \"ee\", \"ff\" };\n    for (std::string word; std::cout << \"Enter plz:\\n\", std::cin >> word; )\n    {\n        auto is_excluded = std::binary_search(exclude.cbegin(), exclude.cend(), word);\n        auto reply = is_excluded ? \"excluded\" : \"not excluded\";\n        std::cout << reply << std::endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch11/ex11_9_10.cpp",
    "content": "// @Alan\n//\n// Exercise 11.9:\n// Define a map that associates words with a list of\n// line numbers on which the word might occur.\n//\n// Exercise 11.10:\n// Could we define a map from vector<int>::iterator\n// to int? What about from list<int>::iterator to int?\n// In each case, if not, why not?\n//  vector<int>::iterator to int is ok , because < is defined\n//  list<int>::iterator to int is not ok, as no < is defined.\n#include <iostream>\n#include <map>\n#include <string>\n#include <algorithm>\n#include <list>\n#include <vector>\n\nint main()\n{\n    // ex 11.9\n    std::map<std::string, std::list<std::size_t>> m;\n\n    // ex 11.10\n    // can be declared.\n    std::map<std::vector<int>::iterator, int> mv;\n    std::map<std::list<int>::iterator, int> ml;\n\n\n    std::vector<int> vi;\n    mv.insert(std::pair<std::vector<int>::iterator, int>(vi.begin(), 0));\n\n    // but when using this one the compiler complained that\n    // error: no match for 'operator<' in '__x < __y'\n    std::list<int> li;\n    ml.insert(std::pair<std::list<int>::iterator, int>(li.begin(), 0));\n\n    return 0;\n}\n"
  },
  {
    "path": "ch12/README.md",
    "content": "# Chapter 12. Dynamic Memory\n\n## Exercise 12.1:\n>How many elements do b1 and b2 have at the end of this code?\n```cpp\nStrBlob b1;\n{\n    StrBlob b2 = { \"a\", \"an\", \"the\" };\n    b1 = b2;\n    b2.push_back(\"about\");\n}\n```\n\nAt the end of this code,\n * `b1` holds 4 elements;\n * `b2` has been destroyed automatically. So it's meaningless to say how many elements in `b2`.\n\n## Exercise 12.2\n\n[StrBlob](ex12_02.h) | [TEST](ex12_02_TEST.cpp)\n\n## Exercise 12.3:\n>Does this class need const versions of push_back and pop_back? If so, add them. If not, why aren’t they needed?\n\nYou can certainly do this if you want to, but there doesn't seem to be any\nlogical reason. The compiler doesn't complain because this doesn't modify\ndata (which is a pointer) but rather the thing data points to, which is\nperfectly legal to do with a const pointer. by David Schwartz.\n\n-----\n\nDiscussion over this exercise on [Stack Overflow](http://stackoverflow.com/questions/20725190/operating-on-dynamic-memory-is-it-meaningful-to-overload-a-const-memeber-functi)\n\nDiscussion over this exercise more on [douban](http://www.douban.com/group/topic/61573279/)(chinese)\n\n## Exercise 12.4:\n>In our check function we didn’t check whether i was greater than zero. Why is it okay to omit that check?\n\nBecause the type of `i` is `std::vector<std::string>::size_type` which\nis an `unsigned`.When any argument less than 0 is passed in, it will convert\nto a number greater than 0. In short `std::vector<std::string>::size_type`\nwill ensure it is a positive number or 0.\n\n## Exercise 12.5:\n>We did not make the constructor that takes an initializer_list explicit (7.5.4, p. 296). Discuss the pros and cons of this design choice.\n\n[@Mooophy](https://github.com/Mooophy):\n\nkeyword `explicit` prevents automatic conversion from an `initializer_list` to `StrBlob`.\nThis design choice would easy to use but hard to debug.\n\n[@pezy](https://github.com/pezy):\n\n**Pros**\n\n- The compiler will not use this constructor **in an automatic conversion**.\n- We can realize clearly which class we have used.\n\n**Cons**\n\n- We always uses the constructor to construct **a temporary StrBlob object**.\n- cannot use the copy form of initialization with an explicit constructor. not easy to use.\n\n## [Exercise 12.6](ex12_06.cpp)\n## [Exercise 12.7](ex12_07.cpp)\n\n## Exercise 12.8:\n>Explain what if anything is wrong with the following function.\n```cpp\nbool b() {\n    int* p = new int;\n    // ...\n    return p;\n}\n```\n\nThe p will convert to a bool , which means that the dynamic memory allocated has no chance to be freed. As a result, memory leakage will occur.\n\n## Exercise 12.9:\n>Explain what happens in the following code:\n```cpp\nint *q = new int(42), *r = new int(100);\nr = q;\nauto q2 = make_shared<int>(42), r2 = make_shared<int>(100);\nr2 = q2;\n```\n\n- to `q` and `r`:\n\nMemory leakage happens. Because after `r = q` was executed, no pointer points to the int `r` had pointed to. It implies that no chance to free the memory for it.\n\n- to `q2` and `r2`:\n\nIt's safe. Because after 'r2 = q2', the reference count belongs to r2 reduce to 0 and the reference count belongs to q2 increase to 2, then the memory allocated by r2 will be released automatically.\n\n## [Exercise 12.10](ex12_10.cpp)\n## [Exercise 12.11](ex12_11.cpp)\n## [Exercise 12.12](ex12_12.cpp)\n## [Exercise 12.13](ex12_13.cpp)\n## [Exercise 12.14](ex12_14.cpp)\n## [Exercise 12.15](ex12_15.cpp)\n## [Exercise 12.16](ex12_16.cpp)\n## [Exercise 12.17 and 12.18](ex12_17_18.cpp)\n## Exercise 12.19 [Header](ex12_19.h)|[Implementation](ex12_19.cpp)\n## [Exercise 12.20](ex12_20.cpp)\n## Exercise 12.21:\n>We could have written StrBlobPtr’s deref member as follows:\n```cpp\nstd::string& deref() const\n{ return (*check(curr, \"dereference past end\"))[curr]; }\n```\nWhich version do you think is better and why?\n\nThe original one is better, because it's more readable.\n\n## Exercise 12.22 [Header](ex12_22.h)|[Implementation](ex12_22.cpp)\n## [Exercise 12.23](ex12_23.cpp)\n## [Exercise 12.24](ex12_24.cpp)\n\n## Exercise 12.25:\n>Given the following new expression, how would you delete pa?\n```cpp\nint *pa = new int[10];\n```\n\n```cpp\ndelete [] pa;\n```\n\n## [Exercise 12.26](ex12_26.cpp)\n## Exercise 12.27 [Header](ex12_27_30.h)|[Implementation](ex12_27_30.cpp)|[Test](ex12_27_30_TEST.cpp)\n\n## [Exercise 12.28](ex12_28.cpp)\n\n## Exercise 12.29:\n>We could have written the loop to manage the interaction with the user as a do while (5.4.4, p. 189) loop. Rewrite the loop to use a do while. Explain which version you prefer and why.\n\n```cpp\ndo {\n    std::cout << \"enter word to look for, or q to quit: \";\n    string s;\n    if (!(std::cin >> s) || s == \"q\") break;\n    print(std::cout, tq.query(s)) << std::endl;\n} while ( true );\n```\n\nI prefer `do while`, because it looks clearer.\n\n## Exercise 12.30 [Header](ex12_27_30.h)|[Implementation](ex12_27_30.cpp)|[Test](ex12_27_30_TEST.cpp)\n\n## Exercise 12.31:\n>What difference(s) would it make if we used a vector instead of a set to hold the line numbers? Which approach is better? Why?\n\n`vector` doesn't guarantee that elements being held are unique, so `set` is a better choice for this case.\n\n## Exercise 12.32 [Header](ex12_32.h)|[Implementation](ex12_32.cpp)|[Test](ex12_32_TEST.cpp)\n## Exercise 12.33 [Header](ex12_33.h)|[Implementation](ex12_33.cpp)|[Test](ex12_33_TEST.cpp)\n"
  },
  {
    "path": "ch12/ex12_02.h",
    "content": "//\n//  ex12_02.cpp\n//  Exercise 12.2\n//\n//  Created by pezy on 12/22/14.\n//\n//  Write your own version of the StrBlob class including the const versions of front and back.\n\n#include <vector>\n#include <string>\n#include <initializer_list>\n#include <memory>\n#include <exception>\n\nusing std::vector; using std::string;\n\nclass StrBlob {\npublic:\n    using size_type = vector<string>::size_type;\n\n    StrBlob():data(std::make_shared<vector<string>>()) { }\n    StrBlob(std::initializer_list<string> il):data(std::make_shared<vector<string>>(il)) { }\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void pop_back() {\n        check(0, \"pop_back on empty StrBlob\");\n        data->pop_back();\n    }\n\n    std::string& front() {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n\n    std::string& back() {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\n    const std::string& front() const {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n    const std::string& back() const {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\nprivate:\n    void check(size_type i, const string &msg) const {\n        if (i >= data->size()) throw std::out_of_range(msg);\n    }\n\nprivate:\n    std::shared_ptr<vector<string>> data;\n};\n"
  },
  {
    "path": "ch12/ex12_02_TEST.cpp",
    "content": "#include \"ex12_02.h\"\n#include <iostream>\n\nint main()\n{\n    const StrBlob csb{ \"hello\", \"world\", \"pezy\" };\n    StrBlob sb{ \"hello\", \"world\", \"Mooophy\" };\n\n    std::cout << csb.front() << \" \" << csb.back() << std::endl;\n    sb.back() = \"pezy\";\n    std::cout << sb.front() << \" \" << sb.back() << std::endl;\n}\n"
  },
  {
    "path": "ch12/ex12_06.cpp",
    "content": "/***************************************************************************\n*  @file       The code is for the exercises in C++ Primmer 5th Edition\n*  @author     Yue Wang\n*  @date       22  DEC 2013\n*              Jun 2015\n*              Oct 2015\n*  @remark\n***************************************************************************/\n//\n// Exercise 12.6:\n// Write a function that returns a dynamically allocated vector of ints.\n// Pass that vector to another function that reads the standard input to\n// give values to the elements. Pass the vector to another function to print\n// the values that were read.\n// Remember to delete the vector at the appropriate time.\n//\n\n#include <iostream>\n#include <vector>\n\nusing Ptr = std::vector<int>*;\n\nauto make_dynamically()\n{\n    return new std::vector < int > { };\n}\n\nauto populate(Ptr vec)\n{\n    for (int i; std::cout << \"Pls Enter:\\n\", std::cin >> i; vec->push_back(i));\n    return vec;\n}\n\nauto print(Ptr vec) -> std::ostream&\n{\n    for (auto i : *vec) std::cout << i << \" \";\n    return std::cout;\n}\n\nint main()\n{\n    auto vec = populate(make_dynamically());\n    print(vec) << std::endl;\n    delete vec;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch12/ex12_07.cpp",
    "content": "/***************************************************************************\n*  @file       The code is for the exercises in C++ Primmer 5th Edition\n*  @author     Yue Wang\n*  @date       22  DEC 2013\n*                  Oct 2015\n*  @remark\n***************************************************************************/\n//\n// Exercise 12.6:\n// Write a function that returns a dynamically allocated vector of ints.\n// Pass that vector to another function that reads the standard input to\n// give values to the elements. Pass the vector to another function to print\n// the values that were read.\n// Remember to delete the vector at the appropriate time.\n//\n// Exercise 12.7:\n// Redo the previous exercise, this time using shared_ptr.\n//\n\n#include <iostream>\n#include <vector>\n#include <memory>\n\nusing Sptr = std::shared_ptr < std::vector<int> > ;\n\nauto make_with_shared_ptr()\n{\n    return std::make_shared<std::vector<int>>();\n}\n\nauto populate(Sptr vec)\n{\n    for (int i; std::cout << \"Pls Enter:\\n\", std::cin >> i; vec->push_back(i));\n    return vec;\n}\n\nauto print(Sptr vec) -> std::ostream&\n{\n    for (auto i : *vec) std::cout << i << \" \";\n    return std::cout;\n}\n\nint main()\n{\n    auto vec = populate(make_with_shared_ptr());\n    print(vec) << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch12/ex12_10.cpp",
    "content": "/***************************************************************************\n*  @file       The code is for the exercises in C++ Primmer 5th Edition\n*  @author     Yue Wang\n*  @date       23  DEC 2013\n*  @remark\n***************************************************************************/\n//\n// Exercise 12.10:\n// Explain whether the following call to the process function defined on page\n// 464 is correct. If not, how would you correct the call?\n//  correct.\n\n#include <iostream>\n#include <memory>\n\nvoid process(std::shared_ptr<int> ptr)\n{\n    std::cout << \"inside the process function:\" << ptr.use_count() << \"\\n\";\n}\n\nint main()\n{\n    std::shared_ptr<int> p(new int(42));\n    process(std::shared_ptr<int>(p));\n\n    /**\n    * codes below shows how the reference count change.\n    */\n    std::cout << p.use_count() << \"\\n\";\n    auto q = p;\n    std::cout << p.use_count() << \"\\n\";\n    std::cout << \"the int p now points to is:\" << *p << \"\\n\";\n    return 0;\n}\n"
  },
  {
    "path": "ch12/ex12_11.cpp",
    "content": "/***************************************************************************\n *  @file       The code is for the exercises in C++ Primmer 5th Edition\n *  @author     Alan.W\n *  @date       23  DEC 2013\n *  @remark\n ***************************************************************************/\n//\n// Exercise 12.11:\n// What would happen if we called process as follows?\n//  An error was generated at run time : double free or corruption.\n//  See the comments below.\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <memory>\n\nvoid process(std::shared_ptr<int> ptr)\n{\n    std::cout << \"inside the process function:\" << ptr.use_count() << \"\\n\";\n}\n\nint main()\n{\n    std::shared_ptr<int> p(new int(42));\n    /**\n     * @brief   std::shared_ptr<int>(p.get()) construct a temporary shared_ptr and copy it\n     *          to the parameter.However it is not a copy of p. As a result, at end of this\n     *          main function p will free the memory that has been freed inside process ().\n     *          That's why \"double freed or corruption\" was generated.\n     */\n    process(std::shared_ptr<int>(p.get()));\n    return 0;\n}\n"
  },
  {
    "path": "ch12/ex12_12.cpp",
    "content": "/***************************************************************************\n *  @file       The code is for the exercises in C++ Primmer 5th Edition\n *  @author     Alan.W\n *  @date       23  DEC 2013\n *  @remark\n ***************************************************************************/\n//\n// Exercise 12.12:\n// Using the declarations of p and sp explain each of the following calls to\n// process. If the call is legal, explain what it does. If the call is illegal,\n// explain why:\n//  See comments below.\n//\n\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <memory>\n\n\nvoid process(std::shared_ptr<int> ptr)\n{\n    std::cout << \"inside the process function:\" << ptr.use_count() << \"\\n\";\n}\n\nint main()\n{\n    auto p = new int();\n    auto sp = std::make_shared<int>();\n\n    /** @brief\n     *  legal. Just copy sp which is a shared_ptr to process().\n     */\n    //process(sp);\n\n    /** @brief\n     *  illegale.plain pointer can not convert to smart pointer implicitly.\n     */\n    //process(new int());\n\n    /** @brief\n     *  illegale.plain pointer can not convert to smart pointer implicitly.\n     */\n    //process(p);\n\n    /** @brief\n     *  Legal. But it's a bad practice to do so. \n     *  Because using smart pointer together with raw pointer could potentially cause problems. \n     *  For example double free as shown in #145.\n     * \n     *  Check issue #145 for detail, thx @endyul for reporting\n     */\n    //process(std::shared_ptr<int>(p));\n\n\n    return 0;\n}\n"
  },
  {
    "path": "ch12/ex12_13.cpp",
    "content": "// @Yue Wang\n//\n// ex12.13 What happens if we excute the following code?\n//\n//  generate a runtime error : double free\n//\n\n#include <iostream>\n#include <memory>\n\nint main()\n{\n    {\n        auto sp = std::make_shared<int>();\n        auto p = sp.get();\n        delete p;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch12/ex12_14.cpp",
    "content": "//\n//  ex12_14.cpp\n//  Exercise 12.14\n//\n//  Created by pezy on 12/22/14.\n//\n//  Write your own version of a function that uses a shared_ptr to manage a connection.\n\n#include <iostream>\n#include <string>\n#include <memory>\n\nstruct connection {\n    std::string ip;\n    int port;\n    connection(std::string ip_, int port_):ip(ip_), port(port_){ }\n};\nstruct destination {\n    std::string ip;\n    int port;\n    destination(std::string ip_, int port_):ip(ip_), port(port_){ }\n};\n\nconnection connect(destination* pDest)\n{\n    std::shared_ptr<connection> pConn(new connection(pDest->ip, pDest->port));\n    std::cout << \"creating connection(\" << pConn.use_count() << \")\" << std::endl;\n    return *pConn;\n}\n\nvoid disconnect(connection pConn)\n{\n    std::cout << \"connection close(\" << pConn.ip << \":\" << pConn.port << \")\" << std::endl;\n}\n\nvoid end_connection(connection *pConn)\n{\n    disconnect(*pConn);\n}\n\nvoid f(destination &d)\n{\n    connection conn = connect(&d);\n    std::shared_ptr<connection> p(&conn, end_connection);\n    std::cout << \"connecting now(\" << p.use_count() << \")\" << std::endl;\n}\n\nint main()\n{\n    destination dest(\"202.118.176.67\", 3316);\n    f(dest);\n}\n"
  },
  {
    "path": "ch12/ex12_15.cpp",
    "content": "//\n//  ex12_15.cpp\n//  Exercise 12.15\n//\n//  Created by pezy on 12/22/14.\n//\n//  Rewrite the first exercise to use a lambda (10.3.2, p.388) in place of the end_connection function.\n\n#include <iostream>\n#include <string>\n#include <memory>\n\nstruct connection {\n    std::string ip;\n    int port;\n    connection(std::string ip_, int port_):ip(ip_), port(port_){ }\n};\nstruct destination {\n    std::string ip;\n    int port;\n    destination(std::string ip_, int port_):ip(ip_), port(port_){ }\n};\n\nconnection connect(destination* pDest)\n{\n    std::shared_ptr<connection> pConn(new connection(pDest->ip, pDest->port));\n    std::cout << \"creating connection(\" << pConn.use_count() << \")\" << std::endl;\n    return *pConn;\n}\n\nvoid disconnect(connection pConn)\n{\n    std::cout << \"connection close(\" << pConn.ip << \":\" << pConn.port << \")\" << std::endl;\n}\n\nvoid f(destination &d)\n{\n    connection conn = connect(&d);\n    std::shared_ptr<connection> p(&conn, [](connection *p){ disconnect(*p); });\n    std::cout << \"connecting now(\" << p.use_count() << \")\" << std::endl;\n}\n\nint main()\n{\n    destination dest(\"202.118.176.67\", 3316);\n    f(dest);\n}\n"
  },
  {
    "path": "ch12/ex12_16.cpp",
    "content": "//\n//  ex12_15.cpp\n//  Exercise 12.15\n//\n//  Created by pezy on 12/22/14.\n//\n//  Compilers don’t always give easy-to-understand error messages if we attempt to\n//  copy or assign a unique_ptr. Write a program that contains these errors to see\n//  how your compiler diagnoses them.\n\n#include <iostream>\n#include <string>\n#include <memory>\n\nusing std::string; using std::unique_ptr;\n\nint main()\n{\n    unique_ptr<string> p1(new string(\"pezy\"));\n    // unique_ptr<string> p2(p1); // copy\n    //                      ^\n    // Error: Call to implicitly-deleted copy constructor of 'unique_ptr<string>'\n    //\n    // unique_ptr<string> p3 = p1; // assign\n    //                      ^\n    // Error: Call to implicitly-deleted copy constructor of 'unique_ptr<string>'\n    std::cout << *p1 << std::endl;\n    p1.reset(nullptr);\n}\n"
  },
  {
    "path": "ch12/ex12_17_18.cpp",
    "content": "/***************************************************************************\n *  @file       The code is for the exercises in C++ Primmer 5th Edition\n *  @author     Alan.W\n *  @date       24  DEC 2013\n *  @remark\n ***************************************************************************/\n//\n// Exercise 12.17:\n// Which of the following unique_ptr declarations are illegal or likely to\n// result in subsequent program error? Explain what the problem is with each\n// one.\n//\n// Exercise 12.18:\n// Why doesn’t shared_ptr have a release member?\n//  Because other shared_ptr that points the same object can still delete this\n//  object.Thus, it's meaningless to provide this member\n//  more detail can be found a thread on Stack Overflow:\n//  http://stackoverflow.com/questions/1525764/how-to-release-pointer-from-boostshared-ptr\n\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <memory>\n\n\nint main()\n{\n    int ix = 1024, *pi = &ix, *pi2 = new int(2048);\n    typedef std::unique_ptr<int> IntP;\n\n\n    /**\n     * @brief  error: invalid conversion from 'int' to 'std::unique_ptr<int>::pointer { aka int* }' [-fpermissive]\n     */\n    //IntP p0(ix);\n\n\n    /**\n     * @brief The code below can compile, but will cause error at run time.\n     *        The reason is that when the unique_ptr p1 is out of scope, delete will be called\n     *        to free th object. But the object is not allocate using new.Thus, an error\n     *        would be thrown by operating system.\n     *  @badcode\n     */\n    //IntP p1(pi);\n\n\n    /**\n     * @brief This code can compile, but cause a dangling pointer at run time.\n     *        The reason is that the unique_ptr will free the object the raw pointer\n     *        is pointing to.\n     * @badcode\n     */\n    //{ IntP p2(pi2); }\n\n\n    /**\n     * @brief   When the unique_ptr goes out of scope, it will call delete to free an\n     *          obeject not allocated using new.\n     * @badcode\n     */\n    //IntP p3(&ix);\n\n\n    /**\n     * @brief   Recommended.\n     */\n    //IntP p4(new int(2048));\n\n\n    /**\n     * @brief   error:   double free or corruption at run time\n     *          two unique_ptr are pointing to the same object. Thus, when both are out of\n     *          scope, Operating system will throw double free or corruption.\n     * @badcode\n     */\n    //IntP p2(new int(555));\n    //IntP p5(p2.get());\n\n    return 0;\n}\n"
  },
  {
    "path": "ch12/ex12_19.cpp",
    "content": "//\n//  ex12_19.cpp\n//  Exercise 12.19\n//\n//  Created by pezy on 12/26/14.\n//\n//  Define your own version of StrBlobPtr and\n//  update your StrBlob class with the appropriate friend declaration and begin and end members.\n//\n//  @See    ex12_19.h\n\n#include \"ex12_19.h\"\n\nStrBlobPtr StrBlob::begin()\n{\n    return StrBlobPtr(*this);\n}\nStrBlobPtr StrBlob::end()\n{\n    return StrBlobPtr(*this, data->size());\n}\n"
  },
  {
    "path": "ch12/ex12_19.h",
    "content": "//\n//  ex12_19.h\n//  Exercise 12.19\n//\n//  Created by pezy on 12/26/14.\n//\n//  Define your own version of StrBlobPtr and\n//  update your StrBlob class with the appropriate friend declaration and begin and end members.\n//\n//  @See    ex12_02.h\n\n#ifndef CP5_ex12_19_h\n#define CP5_ex12_19_h\n\n#include <vector>\n#include <string>\n#include <initializer_list>\n#include <memory>\n#include <stdexcept>\nusing std::vector; using std::string;\n\nclass StrBlobPtr;\n\nclass StrBlob {\npublic:\n    using size_type = vector<string>::size_type;\n    friend class StrBlobPtr;\n\n    StrBlobPtr begin();\n    StrBlobPtr end();\n\n    StrBlob():data(std::make_shared<vector<string>>()) { }\n    StrBlob(std::initializer_list<string> il):data(std::make_shared<vector<string>>(il)) { }\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void pop_back() {\n        check(0, \"pop_back on empty StrBlob\");\n        data->pop_back();\n    }\n\n    std::string& front() {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n\n    std::string& back() {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\n    const std::string& front() const {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n    const std::string& back() const {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\nprivate:\n    void check(size_type i, const string &msg) const {\n        if (i >= data->size()) throw std::out_of_range(msg);\n    }\n\nprivate:\n    std::shared_ptr<vector<string>> data;\n};\n\nclass StrBlobPtr {\npublic:\n    StrBlobPtr():curr(0) { }\n    StrBlobPtr(StrBlob &a, size_t sz = 0):wptr(a.data), curr(sz) { }\n    bool operator!=(const StrBlobPtr& p) { return p.curr != curr; }\n    string& deref() const {\n        auto p = check(curr, \"dereference past end\");\n        return (*p)[curr];\n    }\n    StrBlobPtr& incr() {\n        check(curr, \"increment past end of StrBlobPtr\");\n        ++curr;\n        return *this;\n    }\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t i, const string &msg) const {\n        auto ret = wptr.lock();\n        if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n        if (i >= ret->size()) throw std::out_of_range(msg);\n        return ret;\n    }\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\n#endif\n"
  },
  {
    "path": "ch12/ex12_20.cpp",
    "content": "//\n//  ex12_20.cpp\n//  Exercise 12.20\n//\n//  Created by pezy on 12/26/14.\n//\n//  Write a program that reads an input file a line at a time into\n//  a StrBlob and uses a StrBlobPtr to print each element in that StrBlob.\n\n#include \"ex12_19.h\"\n#include <fstream>\n#include <iostream>\n\nint main()\n{\n    std::ifstream ifs(\"../data/book.txt\");\n    StrBlob blob;\n    for (std::string str; std::getline(ifs, str); )\n        blob.push_back(str);\n    for (StrBlobPtr pbeg(blob.begin()), pend(blob.end()); pbeg != pend; pbeg.incr())\n        std::cout << pbeg.deref() << std::endl;\n}\n"
  },
  {
    "path": "ch12/ex12_22.cpp",
    "content": "//\n//  ex12_22.cpp\n//  CP5\n//\n//  Created by pezy on 1/2/15.\n//\n\n#include \"ex12_22.h\"\n\nConstStrBlobPtr StrBlob::begin() const // should add const\n{\n    return ConstStrBlobPtr(*this);\n}\nConstStrBlobPtr StrBlob::end() const // should add const\n{\n    return ConstStrBlobPtr(*this, data->size());\n}\n"
  },
  {
    "path": "ch12/ex12_22.h",
    "content": "//\n//  ex12_22.cpp\n//  Exercise 12.22\n//\n//  Created by pezy on 12/28/14.\n//\n//  What changes would need to be made to StrBlobPtr to create a class\n//  that can be used with a const StrBlob?\n//  Define a class named ConstStrBlobPtr that can point to a const StrBlob.\n//\n//  @See    ex12_19.h\n\n#ifndef CP5_ex12_22_h\n#define CP5_ex12_22_h\n\n#include <vector>\n#include <string>\n#include <initializer_list>\n#include <memory>\n#include <exception>\n\nusing std::vector; using std::string;\n\nclass ConstStrBlobPtr;\n\nclass StrBlob {\npublic:\n    using size_type = vector<string>::size_type;\n    friend class ConstStrBlobPtr;\n\n    ConstStrBlobPtr begin() const; // should add const\n    ConstStrBlobPtr end() const; // should add const\n\n    StrBlob():data(std::make_shared<vector<string>>()) { }\n    StrBlob(std::initializer_list<string> il):data(std::make_shared<vector<string>>(il)) { }\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void pop_back() {\n        check(0, \"pop_back on empty StrBlob\");\n        data->pop_back();\n    }\n\n    std::string& front() {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n\n    std::string& back() {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\n    const std::string& front() const {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n    const std::string& back() const {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\nprivate:\n    void check(size_type i, const string &msg) const {\n        if (i >= data->size()) throw std::out_of_range(msg);\n    }\n\nprivate:\n    std::shared_ptr<vector<string>> data;\n};\n\nclass ConstStrBlobPtr {\npublic:\n    ConstStrBlobPtr():curr(0) { }\n    ConstStrBlobPtr(const StrBlob &a, size_t sz = 0):wptr(a.data), curr(sz) { } // should add const\n    bool operator!=(ConstStrBlobPtr& p) { return p.curr != curr; }\n    const string& deref() const { // return value should add const\n        auto p = check(curr, \"dereference past end\");\n        return (*p)[curr];\n    }\n    ConstStrBlobPtr& incr() {\n        check(curr, \"increment past end of StrBlobPtr\");\n        ++curr;\n        return *this;\n    }\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t i, const string &msg) const {\n        auto ret = wptr.lock();\n        if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n        if (i >= ret->size()) throw std::out_of_range(msg);\n        return ret;\n    }\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\n#endif\n"
  },
  {
    "path": "ch12/ex12_23.cpp",
    "content": "//\n//  ex12_23.cpp\n//  Exercise 12.23 \n//\n//  Created by pezy on 12/30/14.\n//\n//  Write a program to concatenate two string literals, putting the result in a dynamically allocated array of char. \n//  Write a program to concatenate two library strings that have the same value as the literals used in the first program. \n\n#include <iostream>\n#include <string>\n#include <string.h>\n\nint main()\n{\n    // dynamically allocated array of char\n    char *concatenate_string = new char[strlen(\"hello \" \"world\") + 1]();\n    strcat(concatenate_string, \"hello \");\n    strcat(concatenate_string, \"world\");\n    std::cout << concatenate_string << std::endl;\n    delete [] concatenate_string;\n    \n    // std::string\n    std::string str1{ \"hello \" }, str2{ \"world\" };\n    std::cout << str1 + str2 << std::endl;\n}\n"
  },
  {
    "path": "ch12/ex12_24.cpp",
    "content": "//\n//  ex12_24.cpp\n//  Exercise 12.24\n//\n//  Created by pezy on 12/30/14.\n//\n//  Write a program that reads a string from the standard input into a dynamically allocated character array.\n//  Describe how your program handles varying size inputs.\n//  Test your program by giving it a string of data that is longer than the array size you've allocated.\n\n\n#include <iostream>\n\nint main()\n{\n    // need to tell the size.\n    std::cout << \"How long do you want the string? \";\n    int size{ 0 };\n    std::cin >> size;\n    char *input = new char[size+1]();\n    std::cin.ignore();\n    std::cout << \"input the string: \";\n    std::cin.get(input, size+1);\n    std::cout << input;\n    delete [] input;\n    // Test: if longer than the array size, we will lost the characters which are out of range.\n}\n"
  },
  {
    "path": "ch12/ex12_26.cpp",
    "content": "//\n//  ex12_26.cpp\n//  Exercise 12.26 \n//\n//  Created by pezy on 12/30/14.\n//\n//  Rewrite the program on page 481 using an allocator. \n\n#include <iostream>\n#include <string>\n#include <memory>\n\nvoid input_reverse_output_string(int n)\n{\n    std::allocator<std::string> alloc;\n    auto const p = alloc.allocate(n);\n    std::string s;\n    auto q = p;\n    while (q != p + n && std::cin >> s)\n        alloc.construct(q++, s);\n    \n    while (q != p)\n    {\n        std::cout << *--q << \" \";\n        alloc.destroy(q);\n    }\n    alloc.deallocate(p, n);\n}\n\nint main()\n{\n    input_reverse_output_string(5);\n}\n"
  },
  {
    "path": "ch12/ex12_27_30.cpp",
    "content": "//\n//  ex12_27.cpp\n//  Exercise 12.27\n//\n//  Created by pezy on 12/31/14.\n//\n//  The TextQuery and QueryResult classes use only capabilities that we have already covered.\n//  Without looking ahead, write your own versions of these classes.\n\n#include \"ex12_27_30.h\"\n#include <sstream>\n#include <algorithm>\n\nTextQuery::TextQuery(std::ifstream &ifs) : input(new vector<string>)\n{\n    LineNo lineNo{ 0 };\n    for (string line; std::getline(ifs, line); ++lineNo) {\n        input->push_back(line);\n        std::istringstream line_stream(line);\n        for (string text, word; line_stream >> text; word.clear()) {\n            // avoid read a word followed by punctuation(such as: word, )\n            std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);\n            // use reference avoid count of shared_ptr add.\n            auto &nos = result[word];\n            if (!nos) nos.reset(new std::set<LineNo>);\n            nos->insert(lineNo);\n        }\n    }\n}\n\nQueryResult TextQuery::query(const string& str) const\n{\n    // use static just allocate once.\n    static shared_ptr<std::set<LineNo>> nodata(new std::set<LineNo>);\n    auto found = result.find(str);\n    if (found == result.end()) return QueryResult(str, nodata, input);\n    else return QueryResult(str, found->second, input);\n}\n\nstd::ostream& print(std::ostream &out, const QueryResult& qr)\n{\n    out << qr.word << \" occurs \" << qr.nos->size() << (qr.nos->size() > 1 ? \" times\" : \" time\") << std::endl;\n    for (auto i : *qr.nos)\n        out << \"\\t(line \" << i+1 << \") \" << qr.input->at(i) << std::endl;\n    return out;\n}\n"
  },
  {
    "path": "ch12/ex12_27_30.h",
    "content": "//\n//  ex12_27.h \n//  Exercise 12.27\n//\n//  Created by pezy on 12/31/14.\n//\n//  The TextQuery and QueryResult classes use only capabilities that we have already covered. \n//  Without looking ahead, write your own versions of these classes.\n\n#ifndef CP5_ex12_27_h\n#define CP5_ex12_27_h\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <iostream>\n#include <fstream>\n#include <map>\n#include <set>\n\nclass QueryResult;\nclass TextQuery {\npublic:\n    using LineNo = vector<string>::size_type;\n    TextQuery(std::ifstream &);\n    QueryResult query(const string&) const;\nprivate:\n    shared_ptr<vector<string>> input;\n    std::map<string, shared_ptr<std::set<LineNo>>> result;\n};\n\nclass QueryResult {\npublic:\n    friend std::ostream& print(std::ostream &, const QueryResult&);\npublic:\n    QueryResult(const string &s, shared_ptr<std::set<TextQuery::LineNo>> set, shared_ptr<vector<string>> v) : word(s), nos(set), input(v) { }\nprivate:\n    string word;\n    shared_ptr<std::set<TextQuery::LineNo>> nos;\n    shared_ptr<vector<string>> input;\n};\n\nstd::ostream& print(std::ostream &, const QueryResult&);\n\n#endif\n"
  },
  {
    "path": "ch12/ex12_27_30_TEST.cpp",
    "content": "//\n//  ex12_27_TEST.cpp\n//  Exercise 12.27\n//\n//  Created by pezy on 12/31/14.\n//\n//  The TextQuery and QueryResult classes use only capabilities that we have already covered.\n//  Without looking ahead, write your own versions of these classes.\n\n#include \"ex12_27_30.h\"\n#include <iostream>\n\nvoid runQueries(std::ifstream &infile)\n{\n    TextQuery tq(infile);\n    while (true) {\n        std::cout << \"enter word to look for, or q to quit: \";\n        string s;\n        if (!(std::cin >> s) || s == \"q\") break;\n        print(std::cout, tq.query(s)) << std::endl;\n    }\n}\n\nint main()\n{\n    std::ifstream file(\"../data/storyDataFile.txt\");\n    runQueries(file);\n}\n"
  },
  {
    "path": "ch12/ex12_28.cpp",
    "content": "//\n//  ex12_28.cpp\n//  Exercise 12.28\n//\n//  Created by pezy on 1/1/15.\n//\n//  Write a program to implement text queries without defining classes to manage the data.\n//  Your program should take a file and interact with a user to query for words in that file.\n//  Use vector, map, and set containers to hold the data for the file and\n//  to generate the results for the queries.\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <map>\n#include <set>\n#include <algorithm>\n\nint main()\n{\n    std::ifstream file(\"../data/letter.txt\");\n    vector<string> input;\n    std::map<string, std::set<decltype(input.size())>> dictionary;\n    decltype(input.size()) lineNo{ 0 };\n    \n    for (string line; std::getline(file, line); ++lineNo) {\n        input.push_back(line);\n        std::istringstream line_stream(line);\n        for (string text, word; line_stream >> text; word.clear()) {\n            std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);\n            dictionary[word].insert(lineNo);\n        }\n    }\n    \n    while (true) {\n        std::cout << \"enter word to look for, or q to quit: \";\n        string s;\n        if (!(std::cin >> s) || s == \"q\") break;\n        auto found = dictionary.find(s);\n        if (found != dictionary.end()) {\n            std::cout << s << \" occurs \" << found->second.size() << (found->second.size() > 1 ? \" times\" : \" time\") << std::endl;\n            for (auto i : found->second)\n                std::cout << \"\\t(line \" << i+1 << \") \" << input.at(i) << std::endl;\n        } else std::cout << s << \" occurs 0 time\" << std::endl;\n    }\n}\n"
  },
  {
    "path": "ch12/ex12_32.cpp",
    "content": "//\n//  ex12_32.cpp\n//  Exercise 12.32\n//\n//  Created by pezy on 1/1/15.\n//\n//  Rewrite the TextQuery and QueryResult classes to use a StrBlob\n//  instead of a vector<string> to hold the input file.\n\n#include \"ex12_32.h\"\n#include <sstream>\n#include <algorithm>\n\nTextQuery::TextQuery(std::ifstream &ifs)\n{\n    StrBlob::size_type lineNo{ 0 };\n    for (string line; std::getline(ifs, line); ++lineNo) {\n        file.push_back(line);\n        std::istringstream line_stream(line);\n        for (string text, word; line_stream >> text; word.clear()) {\n            // avoid read a word followed by punctuation(such as: word, )\n            std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);\n            // use reference avoid count of shared_ptr add.\n            auto &nos = result[word];\n            if (!nos) nos.reset(new std::set<StrBlob::size_type>);\n            nos->insert(lineNo);\n        }\n    }\n}\n\nQueryResult TextQuery::query(const string& str) const\n{\n    // use static just allocate once.\n    static shared_ptr<std::set<StrBlob::size_type>> nodate(new std::set<StrBlob::size_type>);\n    auto found = result.find(str);\n    if (found == result.end()) return QueryResult(str, nodate, file);\n    else return QueryResult(str, found->second, file);\n}\n\nstd::ostream& print(std::ostream &out, const QueryResult& qr)\n{\n    out << qr.word << \" occurs \" << qr.nos->size() << (qr.nos->size() > 1 ? \" times\" : \" time\") << std::endl;\n    for (auto i : *qr.nos) {\n        ConstStrBlobPtr p(qr.file, i);\n        out << \"\\t(line \" << i+1 << \") \" << p.deref() << std::endl;\n    }\n    return out;\n}\n"
  },
  {
    "path": "ch12/ex12_32.h",
    "content": "//\n//  ex12_32.h\n//  Exercise 12.32\n//\n//  Created by pezy on 1/1/15.\n//\n//  Rewrite the TextQuery and QueryResult classes to use a StrBlob\n//  instead of a vector<string> to hold the input file.\n\n#ifndef CP5_ex12_32_h\n#define CP5_ex12_32_h\n\n#include \"ex12_22.h\"\nusing std::shared_ptr;\n\n#include <iostream>\n#include <fstream>\n#include <map>\n#include <set>\n\nclass QueryResult;\nclass TextQuery {\npublic:\n    TextQuery(std::ifstream &);\n    QueryResult query(const string&) const;\nprivate:\n    StrBlob file;\n    std::map<string, shared_ptr<std::set<StrBlob::size_type>>> result;\n};\n\nclass QueryResult {\npublic:\n    friend std::ostream& print(std::ostream &, const QueryResult&);\npublic:\n    QueryResult(const string &s, shared_ptr<std::set<StrBlob::size_type>> set, const StrBlob& f) : word(s), nos(set), file(f) { }\nprivate:\n    string word;\n    shared_ptr<std::set<StrBlob::size_type>> nos;\n    StrBlob file;\n};\n\nstd::ostream& print(std::ostream &, const QueryResult&);\n\n#endif\n"
  },
  {
    "path": "ch12/ex12_32_TEST.cpp",
    "content": "//\n//  ex12_27_TEST.cpp\n//  Exercise 12.27\n//\n//  Created by pezy on 12/31/14.\n//\n//  The TextQuery and QueryResult classes use only capabilities that we have already covered.\n//  Without looking ahead, write your own versions of these classes.\n\n#include \"ex12_32.h\"\n#include <iostream>\n\nvoid runQueries(std::ifstream &infile)\n{\n    TextQuery tq(infile);\n    while (true) {\n        std::cout << \"enter word to look for, or q to quit: \";\n        string s;\n        if (!(std::cin >> s) || s == \"q\") break;\n        print(std::cout, tq.query(s)) << std::endl;\n    }\n}\n\nint main()\n{\n    std::ifstream file(\"../data/storyDataFile.txt\");\n    runQueries(file);\n}\n"
  },
  {
    "path": "ch12/ex12_33.cpp",
    "content": "//\n//  ex12_33.cpp\n//  Exercise 12.33\n//\n//  Created by pezy on 1/1/15.\n//\n//  Rewrite the TextQuery and QueryResult classes to use a StrBlob\n//  instead of a vector<string> to hold the input file.\n\n#include \"ex12_33.h\"\n#include <sstream>\n#include <algorithm>\n\nTextQuery::TextQuery(std::ifstream &ifs)\n{\n    StrBlob::size_type lineNo{ 0 };\n    for (string line; std::getline(ifs, line); ++lineNo) {\n        file.push_back(line);\n        std::istringstream line_stream(line);\n        for (string text, word; line_stream >> text; word.clear()) {\n            // avoid read a word followed by punctuation(such as: word, )\n            std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);\n            // use reference avoid count of shared_ptr add.\n            auto &nos = result[word];\n            if (!nos) nos.reset(new std::set<StrBlob::size_type>);\n            nos->insert(lineNo);\n        }\n    }\n}\n\nQueryResult TextQuery::query(const string& str) const\n{\n    // use static just allocate once.\n    static shared_ptr<std::set<StrBlob::size_type>> nodate(new std::set<StrBlob::size_type>);\n    auto found = result.find(str);\n    if (found == result.end()) return QueryResult(str, nodate, file);\n    else return QueryResult(str, found->second, file);\n}\n\nstd::ostream& print(std::ostream &out, const QueryResult& qr)\n{\n    out << qr.word << \" occurs \" << qr.nos->size() << (qr.nos->size() > 1 ? \" times\" : \" time\") << std::endl;\n    for (auto it = qr.begin(); it != qr.end(); ++it) {\n        ConstStrBlobPtr p(*qr.get_file(), *it);\n        out << \"\\t(line \" << *it + 1 << \") \" << p.deref() << std::endl;\n    }\n    return out;\n}\n"
  },
  {
    "path": "ch12/ex12_33.h",
    "content": "//\n//  ex12_33.h\n//  Exercise 12.33\n//\n//  Created by pezy on 1/1/15.\n//\n//  In Chapter 15 we’ll extend our query system and will need some additional members\n//  in the QueryResult class.\n//  Add members named [begin] and [end] that return iterators into the set of line numbers\n//  returned by a given query, and a member named [get_file] that\n//  returns a shared_ptr to the file in the QueryResult object.\n\n#ifndef CP5_ex12_33_h\n#define CP5_ex12_33_h\n\n#include \"ex12_22.h\"\nusing std::shared_ptr;\n\n#include <iostream>\n#include <fstream>\n#include <map>\n#include <set>\n\nclass QueryResult;\nclass TextQuery {\npublic:\n    TextQuery(std::ifstream &);\n    QueryResult query(const string&) const;\nprivate:\n    StrBlob file;\n    std::map<string, shared_ptr<std::set<StrBlob::size_type>>> result;\n};\n\nclass QueryResult {\npublic:\n    using ResultIter = std::set<StrBlob::size_type>::iterator;\n    friend std::ostream& print(std::ostream &, const QueryResult&);\npublic:\n    QueryResult(const string &s, shared_ptr<std::set<StrBlob::size_type>> set, const StrBlob& f) : word(s), nos(set), file(f) { }\n    ResultIter begin() const { return nos->begin(); }\n    ResultIter end() const { return nos->end(); }\n    shared_ptr<StrBlob> get_file() const { return std::make_shared<StrBlob>(file); }\nprivate:\n    string word;\n    shared_ptr<std::set<StrBlob::size_type>> nos;\n    StrBlob file;\n};\n\nstd::ostream& print(std::ostream &, const QueryResult&);\n\n#endif\n"
  },
  {
    "path": "ch12/ex12_33_TEST.cpp",
    "content": "//\n//  ex12_27_TEST.cpp\n//  Exercise 12.27\n//\n//  Created by pezy on 12/31/14.\n//\n//  The TextQuery and QueryResult classes use only capabilities that we have already covered.\n//  Without looking ahead, write your own versions of these classes.\n\n#include \"ex12_33.h\"\n#include <iostream>\n\nvoid runQueries(std::ifstream &infile)\n{\n    TextQuery tq(infile);\n    while (true) {\n        std::cout << \"enter word to look for, or q to quit: \";\n        string s;\n        if (!(std::cin >> s) || s == \"q\") break;\n        print(std::cout, tq.query(s)) << std::endl;\n    }\n}\n\nint main()\n{\n    std::ifstream file(\"../data/storyDataFile.txt\");\n    runQueries(file);\n}\n"
  },
  {
    "path": "ch13/README.md",
    "content": "﻿# Chapter 13. Copy Control\n\n## Exercise 13.1:\n>What is a copy constructor? When is it used?\n\nA copy constructor is a constructor which first parameter is a **reference** to the class type and any additional parameters have **default values**.\n\nWhen copy initialization happens and that copy initialization requires either the copy constructor or the move constructor.\n\n- Define variables using an `=`\n- Pass an object as an argument to a parameter of nonreference type\n- Return an object from a function that has a nonreference return type\n- Brace initialize the elements in an array or the members of an aggregate class\n- Some class types also use copy initialization for the objects they allocate.\n\n## Exercise 13.2:\n> Explain why the following declaration is illegal:\n```cpp\nSales_data::Sales_data(Sales_data rhs);\n```\n\nIf declaration like that, the call would never succeed to call the copy constructor, `Sales_data rhs` is an argument to a parameter, thus, we'd need to use the copy constructor to copy the argument, but to copy the argument, we'd need to call the copy constructor, and so on indefinitely.\n\n## Exercise 13.3:\n>What happens when we copy a `StrBlob`? What about `StrBlobPtrs`?\n\n```cpp\n// added a public member function to StrBlob and StrBlobPrts\nlong count() {\n    return data.use_count(); // and wptr.use_count();\n}\n\n// test codes in main()\nStrBlob str({ \"hello\", \"world\" });\nstd::cout << \"before: \" << str.count() << std::endl; // 1\nStrBlob str_cp(str);\nstd::cout << \"after: \" << str.count() << std::endl;  // 2\n\nConstStrBlobPtr p(str);\nstd::cout << \"before: \" << p.count() << std::endl; // 2\nConstStrBlobPtr p_cp(p);\nstd::cout << \"after: \" << p.count() << std::endl; // 2\n```\n\nwhen we copy a `StrBlob`, the `shared_ptr` member's use_count add one.\n\nwhen we copy a `StrBlobPrts`, the `weak_ptr` member's use_count isn't changed.(cause the count belongs to `shared_ptr`)\n\n## Exercise 13.4:\n>Assuming Point is a class type with a public copy constructor, identify each use of the copy constructor in this program fragment:\n```cpp\nPoint global;\nPoint foo_bar(Point arg) // 1\n{\n    Point local = arg, *heap = new Point(global); // 2, 3\n    *heap = local;\n    Point pa[ 4 ] = { local, *heap }; // 4, 5\n    return *heap; // 6\n}\n```\n\n## [Exercise 13.5](ex13_05.h)\n\n## Exercise 13.6:\n>What is a copy-assignment operator? When is this operator used? What does the synthesized copy-assignment operator do? When is it synthesized?\n\nThe copy-assignment operator is function named `operator=` and takes an argument of the same type as the class.\n\nThis operator is used when assignment occurred.\n\nThe synthesized copy-assignment operator assigns each nonstatic member of the right-hand object to corresponding member of the left-hand object using the copy-assignment operator for the type of that member.\n\nIt is synthesized when the class does not define its own.\n\n## Exercise 13.7:\n>What happens when we assign one StrBlob to another? What about StrBlobPtrs?\n\nIn both cases, shallow copy will happen. All pointers point to the same address. The `use_count` changed the same as 13.3.\n\n## [Exercise 13.8](ex13_08.h)\n\n## Exercise 13.9:\n>What is a destructor? What does the synthesized destructor do? When is a destructor synthesized?\n\nThe destructor is a member function with the name of the class prefixed by a tilde(~).\n\nAs with the copy constructor and the copy-assignment operator, for some classes, the synthesized destructor is defined to disallow objects of the type from being destoryed. Otherwise, the synthesized destructor has an empty function body.\n\nThe compiler defines a synthesized destructor for any class that does not define its own destructor.\n\n## Exercise 13.10:\n>What happens when a StrBlob object is destroyed? What about a StrBlobPtr?\n\nWhen a `StrBlob` object destroyed, the `use_count` of the dynamic object will decrement. It will be freed if no `shared_ptr` to that dynamic object.\n\nWhen a `StrBlobPter` object is destroyed the object dynamically allocated will not be freed.\n\n## [Exercise 13.11](ex13_11.h)\n\n## Exercise 13.12:\n>How many destructor calls occur in the following code fragment?\n```cpp\nbool fcn(const Sales_data *trans, Sales_data accum)\n{\n    Sales_data item1(*trans), item2(accum);\n    return item1.isbn() != item2.isbn();\n}\n```\n\n3 times. There are `accum`, `item1` and `item2`.\n\n## [Exercise 13.13](ex13_13.cpp)\n\n## Exercise 13.14:\n>Assume that `numbered` is a class with a default constructor that generates a unique serial number for each object, which is stored in a data member named `mysn`. Assuming numbered uses the synthesized copy-control members and given the following function:\n```cpp\nvoid f (numbered s) { cout << s.mysn << endl; }\n```\nwhat output does the following code produce?\n```cpp\nnumbered a, b = a, c = b;\nf(a); f(b); f(c);\n```\n\nThree identical numbers.\n\n## Exercise 13.15:\n>Assume `numbered` has a copy constructor that generates a new serial number. Does that change the output of the calls in the previous exercise? If so, why? What output gets generated?\n\nYes, it does. Because, as described, the newly defined copy constructor can handle such situations as expected.Thus, the output will be three different numbers.\n\n## Exercise 13.16:\n>What if the parameter in f were const numbered&? Does that change the output? If so, why? What output gets generated?\n\nYes, the output will change. Because no copy operation happens within function `f`. Thus, the three Output are the same.\n\n## Exercise 13.17\n> Write versions of numbered and f corresponding to the previous three exercises and check whether you correctly predicted the output.\n\n[For 13.14](ex13_17_1.cpp) | [For 13.15](ex13_17_2.cpp) | [For 13.16](ex13_17_3.cpp)\n\n## Exercise 13.18 [.h](ex13_18.h) | [.cpp](ex13_18.cpp)\n\n## [Exercise 13.19](ex13_19.h)\n\n## Exercise 13.20:\n>Explain what happens when we copy, assign, or destroy objects of our TextQuery and QueryResult classes from § 12.3 (p. 484).\n\nThe member (smart pointer and container) will be copied.\n\n## Exercise 13.21:\n>Do you think the TextQuery and QueryResult classes need to define their own versions of the copy-control members? If so, why? If not, why not? Implement whichever copy-control operations you think these classes require.\n\nAs synthesized version meet all requirements for this case, no custom version control memebers need to define. Check [#304](https://github.com/Mooophy/Cpp-Primer/issues/304#issuecomment-124081395) for detail.\n\n## [Exercise 13.22](ex13_22.h)\n\n## Exercise 13.23:\n>Compare the copy-control members that you wrote for the solutions to the previous section’s exercises to the code presented here. Be sure you understand the differences, if any, between your code and ours.\n\nCheck 13.22.\n\n## Exercise 13.24:\n>What would happen if the version of `HasPtr` in this section didn’t define a destructor? What if `HasPtr` didn’t define the copy constructor?\n\nIf `HasPtr` didn't define a destructor, a memory leak would occur, compiler synthesized destructor does not manage dynamic memory. If `HasPtr` didn't define the copy constructor, we would get pointer-like copy behaviour. The ps pointer would be copied to the left hand side, but ps in the lhs and the rhs would still point to the same string on the heap. \n\n## Exercise 13.25:\n>Assume we want to define a version of `StrBlob` that acts like a value. Also assume that we want to continue to use a shared_ptr so that our `StrBlobPtr` class can still use a weak_ptr to the vector. Your revised class will need a copy constructor and copy-assignment operator but will not need a destructor. Explain what the copy constructor and copy-assignment operators must do. Explain why the class does not need a destructor.\n\nCopy constructor and copy-assignment operator should dynamically allocate memory for its own , rather than share the object with the right hand operand.\n\n`StrBlob` is using smart pointers which can be managed with synthesized destructor, If an object of `StrBlob` is out of scope, the destructor for std::shared_ptr will be called automatically to free the memory dynamically allocated when the `use_count` goes to 0.\n\n## Exercise 13.26 [hpp](ex13_26.h) | [cpp](ex13_26.cpp)\n\n## [Exercise 13.27](ex13_27.h)\n\n## Exercise 13.28 [hpp](ex13_28.h) | [cpp](ex13_28.cpp)\n\n## Exercise 13.29:\n> Explain why the calls to swap inside swap(HasPtr&, HasPtr&) do not cause a recursion loop.\n\n`swap(lhs.ps, rhs.ps);` feed the version : `swap(std::string*, std::string*)` and `swap(lhs.i, rhs.i);` feed the version : `swap(int, int)`. Both them can't call `swap(HasPtr&, HasPtr&)`. Thus, the calls don't cause a recursion loop.\n\n## [Exercise 13.30](ex13_30.h)\n## Exercise 13.31 [hpp](ex13_31.h) | [cpp](ex13_31.cpp)\n\n## Exercise 13.32:\n>Would the pointerlike version of `HasPtr` benefit from defining a swap function? If so, what is the benefit? If not, why not?\n\n@Mooophy:\n\nEssentially, the specific avoiding memory allocation is the reason why it improve performance. As for the pointerlike version, no dynamic memory allocation anyway. Thus, a specific version for it will not improve the performance.\n\n## Exercise 13.33:\n>Why is the parameter to the `save` and `remove` members of Message a Folder&? Why didn’t we define that parameter as `Folder`? Or `const Folder&`?\n\nBecause these operations must also update the given `Folder`. Updating a `Folder` is a job that the `Folder` class controls through its `addMsg` and `remMsg` members, which will add or remove a pointer to a given `Message`, respectively.\n\n## Exercise 13.34 [hpp](ex13_34_36_37.h) | [cpp](ex13_34_36_37.cpp)\n\n## Exercise 13.35:\n>What would happen if `Message` used the synthesized versions of the copy-control members?\n\nsome existing `Folders` will out of sync with the `Message` after assignment.\n\n## Exercise 13.36 [hpp](ex13_34_36_37.h) | [cpp](ex13_34_36_37.cpp)\n## Exercise 13.37 [hpp](ex13_34_36_37.h) | [cpp](ex13_34_36_37.cpp)\n\n## Exercise 13.38:\n>We did not use copy and swap to define the Message assignment operator. Why do you suppose this is so?\n\n@Mooophy\nThe copy and swap is an elegant way when working with dynamicly allocated memory. In the Message class , nothing is allocated dynamically. Thus using this idiom makes no sense and will make it more complicated to implement due to the pointers that point back.\n\n@pezy\nIn this case, `swap` function is special. It will be clear two `Message`'s folders , then swap members, and added themselves to each folders. But, `Message` assignment operator just clear itself, and copy the members, and added itself to each folders. The `rhs` don't need to clear and add to folders. So, if using copy and swap to define, it will be very inefficiency.\n\n## Exercise 13.39 [hpp](ex13_39.h) | [cpp](ex13_39.cpp)\n## Exercise 13.40 [hpp](ex13_40.h) | [cpp](ex13_40.cpp)\n\n## Exercise 13.41:\n>Why did we use postfix increment in the call to construct inside push_back? What would happen if it used the prefix increment?\n\n\t|a|b|c|d|f|..............|\n\t^\t       ^             ^\n\telements   first_free    cap\n\n\t// if use alloc.construct(first_free++, \"g\");\n\t|a|b|c|d|f|g|.............|\n\t^\t         ^            ^\n\telements     first_free   cap\n\n\t// if use alloc.construct(++first_free, \"g\");\n\t|a|b|c|d|f|.|g|............|\n\t^\t       ^ ^             ^\n\telements   | first_free    cap\n\t\t       |\n\t    \"unconstructed\"\n\n## Exercise 13.42:\n>Test your StrVec class by using it in place of the vector<string> in your TextQuery and QueryResult classes (12.3, p. 484).\n\n- StrVec : [hpp](ex13_42_StrVec.h) | [cpp](ex13_42_StrVec.cpp)\n- TextQuery and QueryResult : [hpp](ex13_42_TextQuery.h) | [cpp](ex13_42_TextQuery.cpp)\n- Text : [ex13_42.cpp](ex13_42.cpp)\n\n## Exercise 13.43:\n>Rewrite the free member to use `for_each` and a lambda (10.3.2, p. 388) in place of the for loop to destroy the elements. Which implementation do you prefer, and why?\n\n**Rewrite**\n```cpp\nfor_each(elements, first_free, [this](std::string &rhs){ alloc.destroy(&rhs); });\n```\n\n@Mooophy:\nThe new version is better. Compared to the old one, it doesn't need to worry about the order and decrement.So more straightforward and handy. The only thing to do for using this approach is to add \"&\" to build the pointers to string pointers.\n\n## Exercise 13.44:\n>Write a class named String that is a simplified version of the library string class. Your class should have at least a default constructor and a constructor that takes a pointer to a C-style string. Use an allocator to allocate memory that your String class uses.\n\n[hpp](ex13_44_47.h) | [cpp](ex13_44_47.cpp) | [Test](ex13_48.cpp)\n\nmore information to see [A trivial String class that designed for write-on-paper in an interview](https://github.com/chenshuo/recipes/blob/fcf9486f5155117fb8c36b6b0944c5486c71c421/string/StringTrivial.h)\n\n## Exercise 13.45:\n>Distinguish between an rvalue reference and an lvalue reference.\n\nDefinition：\n\n- lvalue reference: reference that can bind to **an lvalue**. (Regular reference)\n- rvalue reference: reference **to an object that is about to be destroyed**.\n\nWe can bind an rvalue reference to expression that require conversion, to literals, or to expressions that return an rvalue, but we cannot directly bind an rvalue reference to an lvalue.\n\n```cpp\nint i = 42;\nint &r = i; // lvalue reference\nint &&rr = i; // rvalue reference (Error: i is a lvalue)\nint &r2 = i*42; // lvalue reference (Error: i*42 is a rvalue)\nconst int &r3 = i*42; // reference to const (bind to a rvalue)\nint &&rr2 = i*42; // rvalue reference\n```\n\n- lvalue : functions that return lvalue references, assignment, subscript, dereference, and prefix increment/decrement operator.\n- rvalue / const reference : functions that return a nonreferences, arithmetic, relational bitwise, postfix increment/decrement operators.\n\n## Exercise 13.46:\n>Which kind of reference can be bound to the following initializers?\n```cpp\nint f();\nvector<int> vi(100);\nint&& r1 = f();\nint& r2 = vi[0];\nint& r3 = r1;\nint&& r4 = vi[0] * f();\n```\n\n## Exercise 13.47 [hpp](ex13_44_47.h) | [cpp](ex13_44_47.cpp)\n\n## [Exercise 13.48](ex13_48.cpp)\n\n## Exercise 13.49:\n>Add a move constructor and move-assignment operator to your StrVec, String, and Message classes.\n\n- StrVec: [hpp](ex13_49_StrVec.h) | [cpp](ex13_49_StrVec.cpp)\n- String: [hpp](ex13_49_String.h) | [cpp](ex13_49_String.cpp)\n- Message:[hpp](ex13_49_Message.h) | [cpp](ex13_49_Message.cpp)\n\n## Exercise 13.50:\n> Put print statements in the move operations in your String class and rerun the program from exercise 13.48 in 13.6.1 (p. 534) that used a vector<String> to see when the copies are avoided.\n\n```cpp\nString baz()\n{\n    String ret(\"world\");\n    return ret; // first avoided\n}\n\nString s5 = baz(); // second avoided\n```\n\n## Exercise 13.51:\n>Although `unique_ptrs` cannot be copied, in 12.1.5 (p. 471) we wrote a clone function that returned a unique_ptr by value. Explain why that function is legal and how it works.\n\nFor such case, move semantics is expected rather than copy operation.That's why a `unique_ptr` may be returned from a function by value.\nReference: [StackOverflow - returning unique pointers from functions] (http://stackoverflow.com/questions/4316727) <br>\n\n## Exercise 13.52:\n>Explain in detail what happens in the assignments of the `HasPtr` objects on page 541. In particular, describe step by step what happens to values of `hp`, `hp2`, and of the `rhs` parameter in the `HasPtr` assignment operator.\n\n`rhs` parameter is nonreference, which means the parameter is **copy initialized**. Depending on the type of the argument, copy initialization uses either the *copy constructor* or the *move constructor*.\n\n**lvalues are copied and rvalues are moved.**\n\nThus, in `hp = hp2;`, `hp2` is an lvalue, copy constructor used to copy `hp2`. In `hp = std::move(hp2);`, move constructor moves `hp2`.\n\n## Exercise 13.53:\n>As a matter of low-level efficiency, the `HasPtr` assignment operator is not ideal. Explain why. Implement a copy-assignment and move-assignment operator for `HasPtr` and compare the operations executed in your new move-assignment operator versus the copy-and-swap version.\n\nnothing to say, just see the versus codes:\n\n[hpp](ex13_53.h) | [cpp](ex13_53.cpp) | [Test](ex13_53_test.cpp)\n\nsee more information at [this question && answer](http://stackoverflow.com/questions/21010371/why-is-it-not-efficient-to-use-a-single-assignment-operator-handling-both-copy-a).\n\n## Exercise 13.54:\n>What would happen if we defined a `HasPtr` move-assignment operator but did not change the copy-and-swap operator? Write code to test your answer.\n\n```sh\nerror: ambiguous overload for 'operator=' (operand types are 'HasPtr' and 'std::remove_reference<HasPtr&>::type { aka HasPtr }')\nhp1 = std::move(*pH);\n^\n```\n\n## Exercise 13.55:\n>Add an rvalue reference version of `push_back` to your `StrBlob`.\n\n```cpp\nvoid push_back(string &&s) { data->push_back(std::move(s)); }\n```\n\n## Exercise 13.56:\n>What would happen if we defined sorted as:\n```cpp\nFoo Foo::sorted() const & {\n    Foo ret(*this);\n    return ret.sorted();\n}\n```\n\nrecursion and stack overflow.\n\n@miaojiuchen:\nBecause the local variable `ret` here is an Lvalue, so when we call `ret.sorted()`, we are actually not calling the member function `Foo Foo::sorted() &&` as expected, but `Foo Foo::sorted() const &` instead. As a result, the code will be trapped into a recursion and causes a deadly stack overflow.\n\n## Exercise 13.57:\n>What if we defined sorted as:\n```cpp\nFoo Foo::sorted() const & { return Foo(*this).sorted(); }\n```\n\nok, it will call the move version.\n\n## Exercise 13.58:\n>Write versions of class Foo with print statements in their sorted functions to test your answers to the previous two exercises.\n\n[Exercise 13.58](ex13_58.cpp)\n"
  },
  {
    "path": "ch13/ex13_05.h",
    "content": "//\n//  ex13_05.h\n//  CP5\n//\n//  Created by pezy on 1/5/15.\n//\n//  Given the following sketch of a class, write a copy constructor that copies all the members.\n//  Your constructor should dynamically allocate a new string and copy the object to which ps points,\n//  rather than copying ps itself.\n\n#ifndef CP5_ex13_05_h\n#define CP5_ex13_05_h\n\n#include <string>\n\nclass HasPtr {\npublic:\n    HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }\n    HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { }\nprivate:\n    std::string *ps;\n    int i;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_08.h",
    "content": "//\n//  ex13_08.h\n//  CP5\n//\n//  Created by pezy on 1/12/15.\n//\n//  Write the assignment operator for the HasPtr class from exercise 13.5 in 13.1.1 (p. 499).\n//  As with the copy constructor, your assignment operator should copy the object to which ps points.\n//\n//  See ex13_05.h\n\n#ifndef CP5_ex13_08_h\n#define CP5_ex13_08_h\n\n#include <string>\n\nclass HasPtr {\npublic:\n    HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }\n    HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }\n    HasPtr& operator=(const HasPtr &rhs_hp) {\n        if(this != &rhs_hp){\n            std::string *temp_ps = new std::string(*rhs_hp.ps);\n            delete ps;\n            ps = temp_ps;\n            i = rhs_hp.i;\n        }\n        return *this;\n    }\nprivate:\n    std::string *ps;\n    int i;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_11.h",
    "content": "//\n//  ex13_11.h\n//  CP5\n//\n//  Created by pezy on 1/13/15.\n//\n//  Add a destructor to your HasPtr class from the previous exercises. \n//\n//  See ex13_08.h \n\n#ifndef CP5_ex13_11_h\n#define CP5_ex13_11_h\n\n#include <string>\n\nclass HasPtr {\npublic:\n    HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }\n    HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }\n    HasPtr& operator=(const HasPtr &hp) {\n        std::string *new_ps = new std::string(*hp.ps);\n        delete ps;\n        ps = new_ps;\n        i = hp.i;\n        return *this;\n    }\n    ~HasPtr() {\n        delete ps;\n    }\nprivate:\n    std::string *ps;\n    int i;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_13.cpp",
    "content": "//\n//  ex13_13.cpp\n//  CP5\n//\n//  Created by pezy on 1/13/15.\n//\n//  A good way to understand copy-control members and constructors is to define a simple class with these members in which each member prints its name:\n//  struct X {\n//    X() { std::cout << \"X()\" << std::endl; }\n//    X(const X&) { std::cout << \"X(const X&)\" << std::endl; }\n//  };\n//  Add the copy-assignment operator and destructor to X and write a program using X objects in various ways:\n//  Pass them as nonreference and reference parameters;\n//  dynamically allocate them;\n//  put them in containers; and so forth.\n//  Study the output until you are certain you understand when and why each copy-control member is used.\n//  As you read the output, remember that the compiler can omit calls to the copy constructor.\n\n#include <iostream>\n#include <vector>\n#include <initializer_list>\n\nstruct X {\n    X() { std::cout << \"X()\" << std::endl; }\n    X(const X&) { std::cout << \"X(const X&)\" << std::endl; }\n    X& operator=(const X&) { std::cout << \"X& operator=(const X&)\" << std::endl; return *this; }\n    ~X() { std::cout << \"~X()\" << std::endl; }\n};\n\nvoid f(const X &rx, X x)\n{\n    std::vector<X> vec;\n    vec.reserve(2);\n    vec.push_back(rx);\n    vec.push_back(x);\n}\n\nint main()\n{\n    X *px = new X;\n    f(*px, *px);\n    delete px;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_17_1.cpp",
    "content": "//\n//  ex13_17.cpp\n//  Exercise 13.17\n//\n//  Created by pezy on 1/15/15.\n//  Refactoed by acgtyrant Aug 2015\n//\n//  Write versions of numbered and f corresponding to the previous three exercises\n//  and check whether you correctly predicted the output.\n//\n//  For 13.14\n\n#include <iostream>\n\nclass numbered {\npublic:\n    numbered() {\n        mysn = unique++;\n    }\n\n    int mysn;\n    static int unique;\n};\n\nint numbered::unique = 10;\n\nvoid f(numbered s) {\n    std::cout << s.mysn << std::endl;\n}\n\nint main()\n{\n    numbered a, b = a, c = b;\n    f(a);\n    f(b);\n    f(c);\n}\n"
  },
  {
    "path": "ch13/ex13_17_2.cpp",
    "content": "//\n//  ex13_17.cpp\n//  Exercise 13.17\n//\n//  Created by pezy on 1/15/15.\n//  Refactoed by acgtyrant Aug 2015\n//\n//  Write versions of numbered and f corresponding to the previous three exercises\n//  and check whether you correctly predicted the output.\n//\n//  For 13.15\n\n#include <iostream>\n\nclass numbered {\npublic:\n    numbered() {\n        mysn = unique++;\n    }\n\n    numbered(const numbered& n) {\n        mysn = unique++;\n    }\n\n    int mysn;\n    static int unique;\n};\n\nint numbered::unique = 10;\n\nvoid f(numbered s) {\n    std::cout << s.mysn << std::endl;\n}\n\nint main()\n{\n    numbered a, b = a, c = b;\n    f(a);\n    f(b);\n    f(c);\n}\n"
  },
  {
    "path": "ch13/ex13_17_3.cpp",
    "content": "//\n//  ex13_17.cpp\n//  Exercise 13.17\n//\n//  Created by pezy on 1/15/15.\n//  Refactoed by acgtyrant Aug 2015\n//\n//  Write versions of numbered and f corresponding to the previous three exercises\n//  and check whether you correctly predicted the output.\n//\n//  For 13.16\n\n#include <iostream>\n\nclass numbered {\npublic:\n    numbered() {\n        mysn = unique++;\n    }\n\n    numbered(const numbered& n) {\n        mysn = unique++;\n    }\n\n    int mysn;\n    static int unique;\n};\n\nint numbered::unique = 10;\n\nvoid f(const numbered& s) {\n    std::cout << s.mysn << std::endl;\n}\n\nint main()\n{\n    numbered a, b = a, c = b;\n    f(a);\n    f(b);\n    f(c);\n}\n"
  },
  {
    "path": "ch13/ex13_18.cpp",
    "content": "//\n//  ex13_18.cpp\n//  Exercise 13.18\n//\n//  Created by pezy on 1/15/15.\n//\n//  Define an Employee class that contains an employee name and a unique employee identifier.\n//  Give the class a default constructor and a constructor that\n//  takes a string representing the employee’s name.\n//  Each constructor should generate a unique ID by incrementing a static data member.\n//\n\n#include \"ex13_18.h\"\n\nint Employee::s_increment = 0;\n\nEmployee::Employee() {\n    id_ = s_increment++;\n}\n\nEmployee::Employee(const string &name) {\n    id_ = s_increment++;\n    name_ = name;\n}\n\nint main()\n{\n\t\n\treturn 0;\n}\n"
  },
  {
    "path": "ch13/ex13_18.h",
    "content": "//\n//  ex13_18.h\n//  Exercise 13.18\n//\n//  Created by pezy on 1/15/15.\n//\n//  Define an Employee class that contains an employee name and a unique employee identifier.\n//  Give the class a default constructor and a constructor that\n//  takes a string representing the employee’s name.\n//  Each constructor should generate a unique ID by incrementing a static data member.\n//\n\n#ifndef CP5_ex13_18_h\n#define CP5_ex13_18_h\n\n#include <string>\nusing std::string;\n\nclass Employee {\npublic:\n    Employee();\n    Employee(const string &name);\n    \n    const int id() const { return id_; }\n    \nprivate:\n    string name_;\n    int id_;\n    static int s_increment;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_19.h",
    "content": "//\n//  ex13_19.h\n//  Exercise 13.19\n//\n//  Created by pezy on 1/15/15.\n//\n//  Does your Employee class need to define its own versions of the copy-control members?\n//  If so, why? If not, why not?\n//  Implement whatever copy-control members you think Employee needs.\n//\n//  Answer: No, cause there really is no sensible meaning. employee can't copy in real world.\n\n#ifndef CP5_ex13_19_h\n#define CP5_ex13_19_h\n\n#include <string>\nusing std::string;\n\nclass Employee {\npublic:\n    Employee();\n    Employee(const string &name);\n    Employee(const Employee&) = delete;\n    Employee& operator=(const Employee&) = delete;\n\n    const int id() const { return id_; }\n\nprivate:\n    string name_;\n    int id_;\n    static int s_increment;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_22.h",
    "content": "//\n//  ex13_22.h\n//  Exercise 13.22\n//\n//  Created by pezy on 1/13/15.\n//\n//  Assume that we want HasPtr to behave like a value. \n//  That is, each object should have its own copy of the string to which the objects point. \n//  We'll show the definitions of the copy-control members in the next section. \n//  However, you already know everything you need to know to implement these members. \n//  Write the HasPtr copy constructor and copyassignment operator before reading on. \n//\n//  See ex13_11.h \n\n#ifndef CP5_ex13_11_h\n#define CP5_ex13_11_h\n\n#include <string>\n\nclass HasPtr {\npublic:\n    HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }\n    HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }\n    HasPtr& operator=(const HasPtr &hp) {\n        auto new_p = new std::string(*hp.ps);\n        delete ps;\n        ps = new_p;\n        i = hp.i;\n        return *this;\n    }\n    ~HasPtr() {\n        delete ps;\n    } \nprivate:\n    std::string *ps;\n    int i;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_26.cpp",
    "content": "//\n//  ex13_26.cpp\n//  Exercise 13.26\n//\n//  Created by pezy on 1/19/15.\n//\n//  Write your own version of the StrBlob class described in the previous exercise.\n//\n//  @See    ex12_22 and ex13_25\n\n#include \"ex13_26.h\"\n\nConstStrBlobPtr StrBlob::begin() const // should add const\n{\n    return ConstStrBlobPtr(*this);\n}\nConstStrBlobPtr StrBlob::end() const // should add const\n{\n    return ConstStrBlobPtr(*this, data->size());\n}\n\nStrBlob& StrBlob::operator=(const StrBlob& sb)\n{\n    data = std::make_shared<vector<string>>(*sb.data);\n    return *this;\n}\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_26.h",
    "content": "//\n//  ex13_26.cpp\n//  Exercise 13.26\n//\n//  Created by pezy on 1/19/15.\n//\n//  Write your own version of the StrBlob class described in the previous exercise.\n//\n//  @See    ex12_22 and ex13_25\n\n#ifndef CP5_ex13_26_h\n#define CP5_ex13_26_h\n\n#include <vector>\n#include <string>\n#include <initializer_list>\n#include <memory>\n#include <exception>\n\nusing std::vector; using std::string;\n\nclass ConstStrBlobPtr;\n\nclass StrBlob {\npublic:\n    using size_type = vector<string>::size_type;\n    friend class ConstStrBlobPtr;\n\n    ConstStrBlobPtr begin() const;\n    ConstStrBlobPtr end() const;\n\n    StrBlob():data(std::make_shared<vector<string>>()) { }\n    StrBlob(std::initializer_list<string> il):data(std::make_shared<vector<string>>(il)) { }\n\n    // copy constructor\n    StrBlob(const StrBlob& sb) : data(std::make_shared<vector<string>>(*sb.data)) { }\n    // copyassignment operators\n    StrBlob& operator=(const StrBlob& sb);\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void pop_back() {\n        check(0, \"pop_back on empty StrBlob\");\n        data->pop_back();\n    }\n\n    string& front() {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n\n    string& back() {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\n    const string& front() const {\n        check(0, \"front on empty StrBlob\");\n        return data->front();\n    }\n    const string& back() const {\n        check(0, \"back on empty StrBlob\");\n        return data->back();\n    }\n\nprivate:\n    void check(size_type i, const string &msg) const {\n        if (i >= data->size()) throw std::out_of_range(msg);\n    }\n\nprivate:\n    std::shared_ptr<vector<string>> data;\n};\n\nclass ConstStrBlobPtr {\npublic:\n    ConstStrBlobPtr():curr(0) { }\n    ConstStrBlobPtr(const StrBlob &a, size_t sz = 0):wptr(a.data), curr(sz) { } // should add const\n    bool operator!=(ConstStrBlobPtr& p) { return p.curr != curr; }\n    const string& deref() const { // return value should add const\n        auto p = check(curr, \"dereference past end\");\n        return (*p)[curr];\n    }\n    ConstStrBlobPtr& incr() {\n        check(curr, \"increment past end of StrBlobPtr\");\n        ++curr;\n        return *this;\n    }\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t i, const string &msg) const {\n        auto ret = wptr.lock();\n        if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n        if (i >= ret->size()) throw std::out_of_range(msg);\n        return ret;\n    }\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_27.h",
    "content": "//\n//  ex13_27.h\n//  Exercise 13.27\n//\n//  Created by pezy on 1/20/15.\n//\n//  Define your own reference-counted version of HasPtr. \n\n#ifndef CP5_ex13_27_h\n#define CP5_ex13_27_h\n\n#include <string>\n\nclass HasPtr {\npublic:\n    HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0), use(new size_t(1)) { }\n    HasPtr(const HasPtr &hp) : ps(hp.ps), i(hp.i), use(hp.use) { ++*use; }\n    HasPtr& operator=(const HasPtr &rhs) {\n        ++*rhs.use;\n        if (--*use == 0) {\n            delete ps;\n            delete use;\n        }\n        ps = rhs.ps;\n        i = rhs.i;\n        use = rhs.use;\n        return *this;\n    }\n    ~HasPtr() {\n        if (--*use == 0) {\n            delete ps;\n            delete use;\n        }\n    } \nprivate:\n    std::string *ps;\n    int i;\n    size_t *use;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_28.cpp",
    "content": "//\n//  ex13_28.cpp\n//  Exercise 13.28\n//\n//  Created by pezy on 1/20/15.\n//\n//  Given the following classes, implement a default constructor and the necessary copy-control members.\n\n#include \"ex13_28.h\"\n\nTreeNode& TreeNode::operator=(const TreeNode &rhs)\n{\n    ++*rhs.count;\n    if (--*count == 0) {\n        delete left;\n        delete right;\n        delete count;\n    }\n    value = rhs.value;\n    left = rhs.left;\n    right = rhs.right;\n    count = rhs.count;\n    return *this;\n}\n\nBinStrTree& BinStrTree::operator=(const BinStrTree &bst)\n{\n    TreeNode *new_root = new TreeNode(*bst.root);\n    delete root;\n    root = new_root;\n    return *this;\n}\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_28.h",
    "content": "//\n//  ex13_28.h\n//  Exercise 13.28\n//\n//  Created by pezy on 1/20/15.\n//\n//  Given the following classes, implement a default constructor and the necessary copy-control members.\n\n#ifndef CP5_ex13_28_h\n#define CP5_ex13_28_h\n\n#include <string>\nusing std::string;\n\nclass TreeNode {\npublic:\n    TreeNode() : value(string()), count(new int(1)), left(nullptr), right(nullptr) { }\n    TreeNode(const TreeNode &rhs) : value(rhs.value), count(rhs.count), left(rhs.left), right(rhs.right) { ++*count; }\n    TreeNode& operator=(const TreeNode &rhs);\n    ~TreeNode() {\n        if (--*count == 0) {\n            delete left;\n            delete right;\n            delete count;\n        }\n    }\n\nprivate:\n    std::string value;\n    int         *count;\n    TreeNode    *left;\n    TreeNode    *right;\n};\n\nclass BinStrTree {\npublic:\n    BinStrTree() : root(new TreeNode()) { }\n    BinStrTree(const BinStrTree &bst) : root(new TreeNode(*bst.root)) { }\n    BinStrTree& operator=(const BinStrTree &bst);\n    ~BinStrTree() { delete root; }\n\nprivate:\n    TreeNode *root;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_30.h",
    "content": "//\n//  ex13_30.h\n//  Exercise 13.30 \n//\n//  Created by pezy on 1/23/15.\n//\n//  Write and test a swap function for your valuelike version of HasPtr. \n//  Give your swap a print statement that notes when it is executed. \n//\n//  See ex13_22.h \n\n#ifndef CP5_ex13_11_h\n#define CP5_ex13_11_h\n\n#include <string>\n#include <iostream>\n\nclass HasPtr {\npublic:\n    friend void swap(HasPtr&, HasPtr&);\n    HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }\n    HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }\n    HasPtr& operator=(const HasPtr &hp) {\n        auto new_p = new std::string(*hp.ps);\n        delete ps;\n        ps = new_p;\n        i = hp.i;\n        return *this;\n    }\n    ~HasPtr() {\n        delete ps;\n    } \n    \n    void show() { std::cout << *ps << std::endl; }\nprivate:\n    std::string *ps;\n    int i;\n};\n\ninline\nvoid swap(HasPtr& lhs, HasPtr& rhs)\n{\n    using std::swap;\n    swap(lhs.ps, rhs.ps);\n    swap(lhs.i, rhs.i);\n    std::cout << \"call swap(HasPtr& lhs, HasPtr& rhs)\" << std::endl;\n}\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_31.cpp",
    "content": "//\n//  ex13_31\n//  Exercise 13.31\n//  Created by Soyn on 21/7/15.\n//  Add the vector<HasPtr>, and sort it.\n//\n//  Refactored by Yue Wang Jul 2015\n//\n#include <vector>\n#include <algorithm>\n#include \"ex13_31.h\"\n\nint main(void)\n{\n    HasPtr s{ \"s\" }, a{ \"a\" }, c{ \"c\" };\n    std::vector<HasPtr> vec{ s, a, c };\n    std::sort(vec.begin(), vec.end());\n\n    for (auto const& elem : vec) elem.show();\n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_31.h",
    "content": "//\n//  ex13_31.h\n//  Exercise 13.31 \n//\n//  Created by pezy on 1/23/15.\n//\n//  Give your class a < operator and define a vector of HasPtrs. \n//  Give that vector some elements and then sort the vector. \n//  Note when swap is called.\n//\n//  Refactored by Yue Wang Jul 2015\n//\n\n#ifndef CP5_ex13_11_h\n#define CP5_ex13_11_h\n\n#include <string>\n#include <iostream>\n\nclass HasPtr \n{\npublic:\n    friend void swap(HasPtr&, HasPtr&);\n    friend bool operator<(const HasPtr &lhs, const HasPtr &rhs);\n\n    HasPtr(const std::string &s = std::string()) \n        : ps(new std::string(s)), i(0) \n    { }\n\n    HasPtr(const HasPtr &hp) \n        : ps(new std::string(*hp.ps)), i(hp.i) \n    { }\n\n    HasPtr& operator=(HasPtr tmp) \n    {\n        this->swap(tmp);\n        return *this;\n    }\n\n    ~HasPtr() \n    {\n        delete ps;\n    }\n\n    void swap(HasPtr &rhs) \n    {\n        using std::swap;\n        swap(ps, rhs.ps);\n        swap(i, rhs.i);\n        std::cout << \"call swap(HasPtr &rhs)\" << std::endl;\n    }\n\n    void show() const\n    { \n        std::cout << *ps << std::endl; \n    }\nprivate:\n    std::string *ps;\n    int i;\n};\n\nvoid swap(HasPtr& lhs, HasPtr& rhs)\n{\n    lhs.swap(rhs);\n}\n\nbool operator<(const HasPtr &lhs, const HasPtr &rhs)\n{\n    return *lhs.ps < *rhs.ps;\n}\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_34_36_37.cpp",
    "content": "#include \"ex13_34_36_37.h\"\n#include <iostream>\n\nvoid swap(Message &lhs, Message &rhs) \n{\n    using std::swap;\n    lhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.\n    rhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.\n    \n    swap(lhs.folders, rhs.folders);\n    swap(lhs.contents, rhs.contents);\n    \n    lhs.add_to_Folders(lhs); // Use existing member function to avoid duplicate code.\n    rhs.add_to_Folders(rhs); // Use existing member function to avoid duplicate code.\n}\n\n// Message Implementation\n\nvoid Message::save(Folder &f) \n{\n    addFldr(&f); // Use existing member function to avoid duplicate code.\n    f.addMsg(this);\n}\n\nvoid Message::remove(Folder &f) \n{\n    remFldr(&f); // Use existing member function to avoid duplicate code.\n    f.remMsg(this);\n}\n\nvoid Message::add_to_Folders(const Message &m) \n{\n    for (auto f : m.folders)\n        f->addMsg(this);\n}\n\nMessage::Message(const Message &m) \n    : contents(m.contents), folders(m.folders) \n{\n    add_to_Folders(m);\n}\n\nvoid Message::remove_from_Folders() \n{\n    for (auto f : folders)\n        f->remMsg(this);\n    // The book added one line here: folders.clear(); but I think it is redundant and more importantly, it will cause a bug:\n    // - In Message::operator=, in the case of self-assignment, it first calls remove_from_Folders() and its folders.clear() \n    //   clears the data member of lhs(rhs), and there is no way we can assign it back to lhs.\n    //   Refer to: http://stackoverflow.com/questions/29308115/protection-again-self-assignment\n    // - Why is it redundant? As its analogous function Message::add_to_Folders(), Message::remove_from_Folders() should ONLY\n    //   take care of the bookkeeping in Folders but not touch the Message's own data members - makes it much clearer and easier\n    //   to use. As you can see in the 2 places where we call Message::remove_from_Folders(): in Message::operator=, folders.clear()\n    //   introduces a bug as illustrated above; in the destructor ~Message(), the member \"folders\" will be destroyed anyways, why do\n    //   we need to clear it first?\n}\n\nMessage::~Message() \n{ \n    remove_from_Folders(); \n}\n\nMessage &Message::operator=(const Message &rhs) \n{\n    remove_from_Folders();\n    contents = rhs.contents;\n    folders = rhs.folders;\n    add_to_Folders(rhs);\n    return *this;\n}\n\nvoid Message::print_debug() \n{ \n    std::cout << contents << std::endl; \n}\n\n// Folder Implementation\n\nvoid swap(Folder &lhs, Folder &rhs) \n{\n    using std::swap;\n    lhs.remove_from_Message();\n    rhs.remove_from_Message();\n\n    swap(lhs.msgs, rhs.msgs);\n    \n    lhs.add_to_Message(lhs);\n    rhs.add_to_Message(rhs);\n}\n\nvoid Folder::add_to_Message(const Folder &f) \n{\n    for (auto m : f.msgs)\n        m->addFldr(this);\n}\n\nFolder::Folder(const Folder &f) \n    : msgs(f.msgs) \n{ \n    add_to_Message(f); \n}\n\nvoid Folder::remove_from_Message() \n{\n    for (auto m : msgs)\n        m->remFldr(this);\n}\n\nFolder::~Folder() \n{ \n    remove_from_Message(); \n}\n\nFolder &Folder::operator=(const Folder &rhs) \n{\n    remove_from_Message();\n    msgs = rhs.msgs;\n    add_to_Message(rhs);\n    return *this;\n}\n\nvoid Folder::print_debug() \n{\n    for (auto m : msgs)\n        std::cout << m->contents << \" \";\n    std::cout << std::endl;\n}\n\nint main() \n{ \n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_34_36_37.h",
    "content": "//\n//  ex13_34_36_37.h\n//  Exercise 13.34 13.36 13.37\n//\n//  Created by pezy on 1/26/15.\n//\n//   34: Write the Message class as described in this section.\n//\n//   36: Design and implement the corresponding Folder class. That class should hold a set that points to the Messages in that Folder.\n//\n//   37:  Add members to the Message class to insert or remove a given Folder* into folders.\n//        These members are analogous to Folder’s addMsg and remMsg operations.\n\n#ifndef CP5_ex13_34_36_37_h\n#define CP5_ex13_34_36_37_h\n\n#include <string>\n#include <set>\n\nclass Folder;\n\nclass Message {\n    friend void swap(Message &, Message &);\n    friend class Folder;\npublic:\n    explicit Message(const std::string &str = \"\"):contents(str) { }\n    Message(const Message&);\n    Message& operator=(const Message&);\n    ~Message();\n    void save(Folder&);\n    void remove(Folder&);\n\n    void print_debug();\n\nprivate:\n    std::string contents;\n    std::set<Folder*> folders;\n\n    void add_to_Folders(const Message&);\n    void remove_from_Folders();\n\n    void addFldr(Folder *f) { folders.insert(f); }\n    void remFldr(Folder *f) { folders.erase(f); }\n};\n\nvoid swap(Message&, Message&);\n\nclass Folder {\n    friend void swap(Folder &, Folder &);\n    friend class Message;\npublic:\n    Folder() = default;\n    Folder(const Folder &);\n    Folder& operator=(const Folder &);\n    ~Folder();\n\n    void print_debug();\n\nprivate:\n    std::set<Message*> msgs;\n\n    void add_to_Message(const Folder&);\n    void remove_from_Message();\n\n    void addMsg(Message *m) { msgs.insert(m); }\n    void remMsg(Message *m) { msgs.erase(m); }\n};\n\nvoid swap(Folder &, Folder &);\n\n#endif // MESSAGE\n\n"
  },
  {
    "path": "ch13/ex13_39.cpp",
    "content": "//\n//  ex13_39.cpp\n//  Exercise 13.39\n//\n//  Created by pezy on 2/3/15.\n//\n//  Write your own version of StrVec, including versions of\n//  reserve, capacity (9.4, p. 356), and resize (9.3.5, p. 352).\n//\n\n#include \"ex13_39.h\"\n\nvoid StrVec::push_back(const std::string &s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n    auto data = alloc.allocate(e - b);\n    return{ data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n    if (elements) {\n        for (auto p = first_free; p != elements;)\n            alloc.destroy(--p);\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n    auto newdata = alloc_n_copy(rhs.begin(), rhs.end());\n    elements = newdata.first;\n    first_free = cap = newdata.second;\n}\n\nStrVec::~StrVec()\n{\n    free();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n    auto data = alloc_n_copy(rhs.begin(), rhs.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n    auto newcapacity = size() ? 2 * size() : 1;\n    alloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n    resize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i)\n            alloc.construct(first_free++, s);\n    }\n    else if (count < size()) {\n        while (first_free != elements + count)\n            alloc.destroy(--first_free);\n    }\n}\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_39.h",
    "content": "//\n//  ex13_39.h\n//  Exercise 13.39 \n//\n//  Created by pezy on 2/3/15.\n//\n//  Write your own version of StrVec, including versions of \n//  reserve, capacity (9.4, p. 356), and resize (9.3.5, p. 352). \n//\n\n#ifndef CP5_EX_13_39_H_\n#define CP5_EX_13_39_H_\n\n#include <memory>\n#include <string>\n\nclass StrVec\n{\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(const StrVec&);\n    StrVec& operator=(const StrVec&);\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_40.cpp",
    "content": "//\n//  ex13_40.cpp\n//  Exercise 13.40\n//\n//  Created by pezy on 2/3/15.\n//\n//  Add a constructor that takes an initializer_list<string> to your StrVec class.\n//\n\n#include \"ex13_40.h\"\n\nvoid StrVec::push_back(const std::string &s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n    auto data = alloc.allocate(e - b);\n    return{ data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n    if (elements) {\n        for (auto p = first_free; p != elements;)\n            alloc.destroy(--p);\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nvoid StrVec::range_initialize(const std::string *first, const std::string *last)\n{\n    auto newdata = alloc_n_copy(first, last);\n    elements = newdata.first;\n    first_free = cap = newdata.second;\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n    range_initialize(rhs.begin(), rhs.end());\n}\n\nStrVec::StrVec(std::initializer_list<std::string> il)\n{\n    range_initialize(il.begin(), il.end());\n}\n\nStrVec::~StrVec()\n{\n    free();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n    auto data = alloc_n_copy(rhs.begin(), rhs.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n    auto newcapacity = size() ? 2 * size() : 1;\n    alloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n    resize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i)\n            alloc.construct(first_free++, s);\n    }\n    else if (count < size()) {\n        while (first_free != elements + count)\n            alloc.destroy(--first_free);\n    }\n}\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_40.h",
    "content": "//\n//  ex13_40.h\n//  Exercise 13.40\n//\n//  Created by pezy on 2/3/15.\n//\n//  Add a constructor that takes an initializer_list<string> to your StrVec class.\n//\n\n#ifndef CP5_EX_13_40_H_\n#define CP5_EX_13_40_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\nclass StrVec\n{\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(const StrVec&);\n    StrVec(std::initializer_list<std::string>);\n    StrVec& operator=(const StrVec&);\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_42.cpp",
    "content": "#include \"ex13_42_TextQuery.h\"\n#include <iostream>\n\nvoid runQueries(std::ifstream &infile)\n{\n    TextQuery tq(infile);\n    while (true) {\n        std::cout << \"enter word to look for, or q to quit: \";\n        std::string s;\n        if (!(std::cin >> s) || s == \"q\") break;\n        print(std::cout, tq.query(s)) << std::endl;\n    }\n}\n\nint main()\n{\n    std::ifstream file(\"../data/storyDataFile.txt\");\n    runQueries(file);\n}\n"
  },
  {
    "path": "ch13/ex13_42_StrVec.cpp",
    "content": "#include \"ex13_42_StrVec.h\"\n\n\nstd::allocator<std::string> StrVec::alloc;\n\nvoid StrVec::push_back(const std::string &s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n    auto data = alloc.allocate(e - b);\n    return{ data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n    if (elements) {\n        for (auto p = first_free; p != elements;)\n            alloc.destroy(--p);\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nvoid StrVec::range_initialize(const std::string *first, const std::string *last)\n{\n    auto newdata = alloc_n_copy(first, last);\n    elements = newdata.first;\n    first_free = cap = newdata.second;\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n    range_initialize(rhs.begin(), rhs.end());\n}\n\nStrVec::StrVec(std::initializer_list<std::string> il)\n{\n    range_initialize(il.begin(), il.end());\n}\n\nStrVec::~StrVec()\n{\n    free();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n    auto data = alloc_n_copy(rhs.begin(), rhs.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n    auto newcapacity = size() ? 2 * size() : 1;\n    alloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n    resize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i)\n            alloc.construct(first_free++, s);\n    }\n    else if (count < size()) {\n        while (first_free != elements + count)\n            alloc.destroy(--first_free);\n    }\n}\n"
  },
  {
    "path": "ch13/ex13_42_StrVec.h",
    "content": "#ifndef CP5_STRVEC_H_\n#define CP5_STRVEC_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\nclass StrVec\n{\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(const StrVec&);\n    StrVec(std::initializer_list<std::string>);\n    StrVec& operator=(const StrVec&);\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    std::string& at(size_t pos) { return *(elements + pos); }\n    const std::string& at(size_t pos) const { return *(elements + pos); }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_42_TextQuery.cpp",
    "content": "#include \"ex13_42_TextQuery.h\"\n#include <sstream>\n#include <algorithm>\n\nusing std::string;\n\nTextQuery::TextQuery(std::ifstream &ifs) : input(new StrVec)\n{\n    size_t lineNo = 0;\n    for (string line; std::getline(ifs, line); ++lineNo) {\n        input->push_back(line);\n        std::istringstream line_stream(line);\n        for (string text, word; line_stream >> text; word.clear()) {\n            // avoid read a word followed by punctuation(such as: word, )\n            std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);\n            // use reference avoid count of shared_ptr add.\n            auto &nos = result[word];\n            if (!nos) nos.reset(new std::set<size_t>);\n            nos->insert(lineNo);\n        }\n    }\n}\n\nQueryResult TextQuery::query(const string& str) const\n{\n    // use static just allocate once.\n    static std::shared_ptr<std::set<size_t>> nodate(new std::set<size_t>);\n    auto found = result.find(str);\n    if (found == result.end()) return QueryResult(str, nodate, input);\n    else return QueryResult(str, found->second, input);\n}\n\nstd::ostream& print(std::ostream &out, const QueryResult& qr)\n{\n    out << qr.word << \" occurs \" << qr.nos->size() << (qr.nos->size() > 1 ? \" times\" : \" time\") << std::endl;\n    for (auto i : *qr.nos)\n        out << \"\\t(line \" << i+1 << \") \" << qr.input->at(i) << std::endl;\n    return out;\n}\n"
  },
  {
    "path": "ch13/ex13_42_TextQuery.h",
    "content": "#ifndef CP5_TEXTQUERY_H_\n#define CP5_TEXTQUERY_H_\n\n#include <string>\n#include <memory>\n#include <iostream>\n#include <fstream>\n#include <map>\n#include <set>\n\n#include \"ex13_42_StrVec.h\"\n\nclass QueryResult;\nclass TextQuery {\npublic:\n    TextQuery(std::ifstream &);\n    QueryResult query(const std::string&) const;\nprivate:\n    std::shared_ptr<StrVec> input;\n\tstd::map<std::string, std::shared_ptr<std::set<size_t>>> result;\n};\n\nclass QueryResult {\npublic:\n    friend std::ostream& print(std::ostream &, const QueryResult&);\npublic:\n    QueryResult(const std::string &s, std::shared_ptr<std::set<size_t>> set, std::shared_ptr<StrVec> v) : word(s), nos(set), input(v) { }\nprivate:\n    std::string word;\n    std::shared_ptr<std::set<size_t>> nos;\n    std::shared_ptr<StrVec> input;\n};\n\nstd::ostream& print(std::ostream &, const QueryResult&);\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_44_47.cpp",
    "content": "#include \"ex13_44_47.h\"\n#include <algorithm>\n#include <iostream>\n\nstd::pair<char*, char*>\nString::alloc_n_copy(const char *b, const char *e)\n{\n    auto str = alloc.allocate(e - b);\n    return{ str, std::uninitialized_copy(b, e, str) };\n}\n\nvoid String::range_initializer(const char *first, const char *last)\n{\n    auto newstr = alloc_n_copy(first, last);\n    elements = newstr.first;\n    end = newstr.second;\n}\n\nString::String(const char *s)\n{\n    char *sl = const_cast<char*>(s);\n    while (*sl)\n        ++sl;\n    range_initializer(s, ++sl);\n}\n\nString::String(const String& rhs)\n{\n    range_initializer(rhs.elements, rhs.end);\n    std::cout << \"copy constructor\" << std::endl;\n}\n\nvoid String::free()\n{\n    if (elements) {\n        std::for_each(elements, end, [this](char &c){ alloc.destroy(&c); });\n        alloc.deallocate(elements, end - elements);\n    }\n}\n\nString::~String()\n{\n    free();\n}\n\nString& String::operator = (const String &rhs)\n{\n    auto newstr = alloc_n_copy(rhs.elements, rhs.end);\n    free();\n    elements = newstr.first;\n    end = newstr.second;\n    std::cout << \"copy-assignment\" << std::endl;\n    return *this;\n}\n"
  },
  {
    "path": "ch13/ex13_44_47.h",
    "content": "#ifndef CP5_STRING_H__\n#define CP5_STRING_H__\n\n#include <memory>\n\nclass String\n{\npublic:\n    String() : String(\"\") { }\n    String(const char *);\n    String(const String&);\n    String& operator=(const String&);\n    ~String();\n\n    const char *c_str() const { return elements; }\n    size_t size() const { return end - elements; }\n    size_t length() const { return end - elements - 1; }\n\nprivate:\n    std::pair<char*, char*> alloc_n_copy(const char*, const char*);\n    void range_initializer(const char*, const char*);\n    void free();\n\nprivate:\n    char *elements;\n    char *end;\n    std::allocator<char> alloc;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_48.cpp",
    "content": "#include \"ex13_44_47.h\"\n#include <vector>\n#include <iostream>\n\n// Test reference to http://coolshell.cn/articles/10478.html\n\nvoid foo(String x)\n{\n    std::cout << x.c_str() << std::endl;\n}\n\nvoid bar(const String& x)\n{\n    std::cout << x.c_str() << std::endl;\n}\n\nString baz()\n{\n    String ret(\"world\");\n    return ret;\n}\n\nint main()\n{\n    char text[] = \"world\";\n\n    String s0;\n    String s1(\"hello\");\n    String s2(s0);\n    String s3 = s1;\n    String s4(text);\n    s2 = s1;\n\n    foo(s1);\n    bar(s1);\n    foo(\"temporary\");\n    bar(\"temporary\");\n    String s5 = baz();\n\n    std::vector<String> svec;\n    svec.reserve(8);\n    svec.push_back(s0);\n    svec.push_back(s1);\n    svec.push_back(s2);\n    svec.push_back(s3);\n    svec.push_back(s4);\n    svec.push_back(s5);\n    svec.push_back(baz());\n    svec.push_back(\"good job\");\n\n    for (const auto &s : svec) {\n        std::cout << s.c_str() << std::endl;\n    }\n}\n"
  },
  {
    "path": "ch13/ex13_49_Message.cpp",
    "content": "#include \"ex13_49_Message.h\"\n#include <iostream>\n\nvoid swap(Message &lhs, Message &rhs)\n{\n    using std::swap;\n    for (auto f : lhs.folders)\n        f->remMsg(&lhs);\n    std::cout << \"Remove message from folders\" << std::endl; // debug\n\n    for (auto f : rhs.folders)\n        f->remMsg(&rhs);\n    std::cout << \"Remove message from folders\" << std::endl; // debug\n\n    swap(lhs.folders, rhs.folders);\n    swap(lhs.contents, rhs.contents);\n\n    std::cout << \"Message members swaped\" << std::endl; // debug\n\n    for (auto f : lhs.folders)\n        f->addMsg(&lhs);\n    std::cout << \"Added message to folders\" << std::endl; // debug\n\n    for (auto f : rhs.folders)\n        f->addMsg(&rhs);\n    std::cout << \"Added message to folders\" << std::endl; // debug\n}\n\nMessage::Message(const Message &m) : contents(m.contents), folders(m.folders)\n{\n    add_to_Folders(m);\n}\n\nMessage::~Message()\n{\n    remove_from_Folders();\n}\n\nvoid Message::save(Folder &f)\n{\n    folders.insert(&f);\n    f.addMsg(this);\n}\n\nvoid Message::remove(Folder &f)\n{\n    folders.erase(&f);\n    f.remMsg(this);\n}\n\nvoid Message::add_to_Folders(const Message &m)\n{\n    for (auto f : m.folders)\n        f->addMsg(this);\n    std::cout << \"Added message to folders\" << std::endl; // debug\n}\n\nvoid Message::remove_from_Folders()\n{\n    for (auto f : folders)\n        f->remMsg(this);\n    std::cout << \"Remove message from folders\" << std::endl; // debug\n}\n\nMessage& Message::operator=(const Message &rhs)\n{\n    remove_from_Folders();\n    contents = rhs.contents;\n    folders = rhs.folders;\n    std::cout << \"Message members assgined\" << std::endl; // debug\n    add_to_Folders(rhs);\n    return *this;\n}\n\nvoid Message::print_debug()\n{\n    std::cout << contents << \": \";\n    for (auto f : folders)\n        std::cout << f->fldr() << \" \";\n    std::cout << std::endl;\n}\n\nvoid Message::move_Folders(Message *m)\n{\n\tfolders = std::move(m->folders);\n\tfor (auto f : folders)\n\t{\n\t\tf->remMsg(m);\n\t\tf->addMsg(this);\n\t}\n\tm->folders.clear();\n}\n\nMessage::Message(Message &&m) : contents(std::move(m.contents))\n{\n    move_Folders(&m);\n}\n\nMessage& Message::operator= (Message &&rhs)\n{\n    if (this != &rhs)\n\t{\n\t\tremove_from_Folders();\n\t\tcontents = std::move(rhs.contents);\n\t\tmove_Folders(&rhs);\n\t}\n\tstd::cout << \"Message members moved\" << std::endl; // debug\n\treturn *this;\n}\n\n// Folder Implementation\n\nvoid swap(Folder &lhs, Folder &rhs)\n{\n    using std::swap;\n    for (auto m : lhs.msgs)\n        m->remFldr(&lhs);\n    std::cout << \"clear folder\" << std::endl; // debug\n\n    for (auto m : rhs.msgs)\n        m->remFldr(&rhs);\n    std::cout << \"clear folder\" << std::endl; // debug\n\n    swap(lhs.name, rhs.name);\n    swap(lhs.msgs, rhs.msgs);\n    std::cout << \"Folder members swaped\" << std::endl; // debug\n\n    for (auto m : lhs.msgs)\n        m->addFldr(&lhs);\n    std::cout << \"Added messages to folder\" << std::endl; // debug\n\n    for (auto m : rhs.msgs)\n        m->addFldr(&rhs);\n    std::cout << \"Added messages to folder\" << std::endl; // debug\n}\n\nvoid Folder::add_to_Message(const Folder &f)\n{\n    for (auto m : f.msgs)\n        m->addFldr(this);\n    std::cout << \"Added messages to folder\" << std::endl; // debug\n}\n\nFolder::Folder(const Folder &f) : name(f.name), msgs(f.msgs)\n{\n    add_to_Message(f);\n}\n\nvoid Folder::remove_from_Message()\n{\n    for (auto m : msgs)\n        m->remFldr(this);\n    std::cout << \"clear folder\" << std::endl; // debug\n}\n\nFolder::~Folder()\n{\n    remove_from_Message();\n}\n\nFolder& Folder::operator =(const Folder &rhs)\n{\n    remove_from_Message();\n    name = rhs.name;\n    msgs = rhs.msgs;\n    std::cout << \"Folder members assigned\" << std::endl; // debug\n    add_to_Message(rhs);\n    return *this;\n}\n\nvoid Folder::print_debug()\n{\n    std::cout << name << \": \";\n    for (auto m : msgs)\n        std::cout << m->msg() << \" \";\n    std::cout << std::endl;\n}\n\nvoid Folder::move_Messages(Folder *f)\n{\n\tmsgs = std::move(f->msgs);\n\tfor (auto m : msgs)\n\t{\n\t\tm->remFldr(f);\n\t\tm->addFldr(this);\n\t}\n\tf->msgs.clear();\n}\n\nFolder::Folder(Folder&& f) : name(std::move(f.name))\n{\n\tmove_Messages(&f);\n}\n\nFolder& Folder::operator=(Folder &&rhs)\n{\n    if (this != &rhs)\n\t{\n\t\tremove_from_Message();\n\t\tname = std::move(rhs.name);\n\t\tmove_Messages(&rhs);\n\t}\n\tstd::cout << \"Message members moved\" << std::endl; // debug\n\treturn *this;\n}\n"
  },
  {
    "path": "ch13/ex13_49_Message.h",
    "content": "#ifndef CP5_MESSAGE_H_\n#define CP5_MESSAGE_H_\n\n#include <string>\n#include <set>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass Folder;\n\nclass Message\n{\n    friend void swap(Message &, Message &);\n    friend void swap(Folder &, Folder &);\n    friend class Folder;\npublic:\n    explicit Message(const std::string &str = \"\") : contents(str) { }\n    Message(const Message&);\n    Message& operator=(const Message&);\n    Message(Message &&m); // need to update the Folders\n    Message& operator=(Message&&); // need to update the Folders\n    ~Message();\n\n    void save(Folder&);\n    void remove(Folder&);\n\n    const std::string& msg() const { return contents; }\n    void print_debug();\n\nprivate:\n    void add_to_Folders(const Message&);\n    void remove_from_Folders();\n\n    void addFldr(Folder *f) { folders.insert(f); }\n    void remFldr(Folder *f) { folders.erase(f); }\n    \n    void move_Folders(Message*); // define function to do the common work\n\nprivate:\n    std::string contents;\n    std::set<Folder*> folders;\n};\n\nvoid swap(Message&, Message&);\n\nclass Folder {\n    friend void swap(Message&, Message&);\n    friend void swap(Folder &, Folder &);\n    friend class Message;\npublic:\n    explicit Folder(const std::string &str = \"\") :name(str) { }\n    Folder(const Folder &);\n    Folder& operator=(const Folder &);\n    Folder(Folder &&f); // need to update the Messages\n    Folder& operator=(Folder &&); // need to update the Messages\n    ~Folder();\n\n    const std::string& fldr() const { return name; }\n    void print_debug();\n\nprivate:\n    std::string name;\n    std::set<Message*> msgs;\n\n    void add_to_Message(const Folder&);\n    void remove_from_Message();\n\n    void addMsg(Message *m) { msgs.insert(m); }\n    void remMsg(Message *m) { msgs.erase(m); }\n    \n    void move_Messages(Folder*); // define function to do the common work\n};\n\nvoid swap(Folder &, Folder &);\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_49_StrVec.cpp",
    "content": "#include \"ex13_49_StrVec.h\"\n#include <algorithm> // for_each\n\nvoid StrVec::push_back(const std::string &s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n    auto data = alloc.allocate(e - b);\n    return{ data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n    if (elements) {\n        for_each(elements, first_free, [this](std::string &rhs){ alloc.destroy(&rhs); });\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nvoid StrVec::range_initialize(const std::string *first, const std::string *last)\n{\n    auto newdata = alloc_n_copy(first, last);\n    elements = newdata.first;\n    first_free = cap = newdata.second;\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n    range_initialize(rhs.begin(), rhs.end());\n}\n\nStrVec::StrVec(std::initializer_list<std::string> il)\n{\n    range_initialize(il.begin(), il.end());\n}\n\nStrVec::~StrVec()\n{\n    free();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n    auto data = alloc_n_copy(rhs.begin(), rhs.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n    auto newcapacity = size() ? 2 * size() : 1;\n    alloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n    resize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i)\n            alloc.construct(first_free++, s);\n    }\n    else if (count < size()) {\n        while (first_free != elements + count)\n            alloc.destroy(--first_free);\n    }\n}\n\nStrVec::StrVec(StrVec &&s) NOEXCEPT : elements(s.elements), first_free(s.first_free), cap(s.cap)\n{\n    // leave s in a state in which it is safe to run the destructor.\n    s.elements = s.first_free = s.cap = nullptr;\n}\n\nStrVec& StrVec::operator = (StrVec &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        free();\n        elements = rhs.elements;\n        first_free = rhs.first_free;\n        cap = rhs.cap;\n        rhs.elements = rhs.first_free = rhs.cap = nullptr;\n    }\n    return *this;\n}\n"
  },
  {
    "path": "ch13/ex13_49_StrVec.h",
    "content": "#ifndef CP5_STRVEC_H_\n#define CP5_STRVEC_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrVec\n{\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(std::initializer_list<std::string>);\n    StrVec(const StrVec&);\n    StrVec& operator=(const StrVec&);\n    StrVec(StrVec&&) NOEXCEPT;\n    StrVec& operator=(StrVec&&)NOEXCEPT;\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    std::string& at(size_t pos) { return *(elements + pos); }\n    const std::string& at(size_t pos) const { return *(elements + pos); }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    static std::allocator<std::string> alloc;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_49_String.cpp",
    "content": "#include \"ex13_49_String.h\"\n#include <algorithm>\n\nstd::pair<char*, char*>\nString::alloc_n_copy(const char *b, const char *e)\n{\n    auto str = alloc.allocate(e - b);\n    return{ str, std::uninitialized_copy(b, e, str) };\n}\n\nvoid String::range_initializer(const char *first, const char *last)\n{\n    auto newstr = alloc_n_copy(first, last);\n    elements = newstr.first;\n    end = newstr.second;\n}\n\nString::String(const char *s)\n{\n    char *sl = const_cast<char*>(s);\n    while (*sl)\n        ++sl;\n    range_initializer(s, ++sl);\n}\n\nString::String(const String& rhs)\n{\n    range_initializer(rhs.elements, rhs.end);\n}\n\nvoid String::free()\n{\n    if (elements) {\n        std::for_each(elements, end, [this](char &c){ alloc.destroy(&c); });\n        alloc.deallocate(elements, end - elements);\n    }\n}\n\nString::~String()\n{\n    free();\n}\n\nString& String::operator = (const String &rhs)\n{\n    auto newstr = alloc_n_copy(rhs.elements, rhs.end);\n    free();\n    elements = newstr.first;\n    end = newstr.second;\n    return *this;\n}\n\nString::String(String &&s) NOEXCEPT : elements(s.elements), end(s.end)\n{\n    s.elements = s.end = nullptr;\n}\n\nString& String::operator = (String &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        free();\n        elements = rhs.elements;\n        end = rhs.end;\n        rhs.elements = rhs.end = nullptr;\n    }\n    return *this;\n}\n"
  },
  {
    "path": "ch13/ex13_49_String.h",
    "content": "#ifndef CP5_STRING_H__\n#define CP5_STRING_H__\n\n#include <memory>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass String\n{\npublic:\n    String() : String(\"\") { }\n    String(const char *);\n    String(const String&);\n    String& operator=(const String&);\n    String(String &&) NOEXCEPT;\n    String& operator=(String&&)NOEXCEPT;\n    ~String();\n\n    const char *c_str() const { return elements; }\n    size_t size() const { return end - elements; }\n    size_t length() const { return end - elements - 1; }\n\nprivate:\n    std::pair<char*, char*> alloc_n_copy(const char*, const char*);\n    void range_initializer(const char*, const char*);\n    void free();\n\nprivate:\n    char *elements;\n    char *end;\n    std::allocator<char> alloc;\n};\n\n#endif\n"
  },
  {
    "path": "ch13/ex13_53.cpp",
    "content": "#include \"ex13_53.h\"\n#include <iostream>\n\ninline void swap(HasPtr &lhs, HasPtr &rhs)\n{\n    using std::swap;\n    swap(lhs.ps, rhs.ps);\n    swap(lhs.i, rhs.i);\n    std::cout << \"call swap\" << std::endl;\n}\n\nHasPtr::HasPtr(const std::string &s) : ps(new std::string(s)), i(0)\n{\n    std::cout << \"call constructor\" << std::endl;\n}\n\nHasPtr::HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i)\n{\n    std::cout << \"call copy constructor\" << std::endl;\n}\n\nHasPtr::HasPtr(HasPtr &&p) noexcept : ps(p.ps), i(p.i)\n{\n    p.ps = 0;\n    std::cout << \"call move constructor\" << std::endl;\n}\n\nHasPtr& HasPtr::operator=(HasPtr rhs)\n{\n    swap(*this, rhs);\n    return *this;\n}\n\nHasPtr::~HasPtr()\n{\n    std::cout << \"call destructor\" << std::endl;\n    delete ps;\n}\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch13/ex13_53.h",
    "content": "#ifndef CP5_ex13_53_h\n#define CP5_ex13_53_h\n\n#include <string>\n\nclass HasPtr {\npublic:\n    friend void swap(HasPtr&, HasPtr&);\n    HasPtr(const std::string &s = std::string());\n    HasPtr(const HasPtr &hp);\n    HasPtr(HasPtr &&p) noexcept;\n    HasPtr& operator=(HasPtr rhs);\n    //HasPtr& operator=(const HasPtr &rhs);\n    //HasPtr& operator=(HasPtr &&rhs) noexcept;\n    ~HasPtr();\n\nprivate:\n    std::string *ps;\n    int i;\n};\n\n#endif // CP5_ex13_53_h\n"
  },
  {
    "path": "ch13/ex13_53_test.cpp",
    "content": "#include \"ex13_53.h\"\n\nint main()\n{\n    HasPtr hp1(\"hello\"), hp2(\"World\"), *pH = new HasPtr(\"World\");\n    hp1 = hp2;\n    hp1 = std::move(*pH);\n}\n"
  },
  {
    "path": "ch13/ex13_58.cpp",
    "content": "#include <vector>\n#include <iostream>\n#include <algorithm>\n\nusing std::vector; using std::sort;\n\nclass Foo {\npublic:\n    Foo sorted() &&;\n    Foo sorted() const &;\nprivate:\n    vector<int> data;\n};\n\nFoo Foo::sorted() && {\n    sort(data.begin(), data.end());\n    std::cout << \"&&\" << std::endl; // debug\n    return *this;\n}\n\nFoo Foo::sorted() const & {\n//    Foo ret(*this);\n//    sort(ret.data.begin(), ret.data.end());\n//    return ret;\n\n    std::cout << \"const &\" << std::endl; // debug\n\n//    Foo ret(*this);\n//    ret.sorted();     // Exercise 13.56\n//    return ret;\n\n    return Foo(*this).sorted(); // Exercise 13.57\n}\n\nint main()\n{\n    Foo().sorted(); // call \"&&\"\n    Foo f;\n    f.sorted(); // call \"const &\"\n}\n"
  },
  {
    "path": "ch14/README.md",
    "content": "# Chapter 14. Overloaded Operations and Conversions\n\n## Exercise 14.1:\n>In what ways does an overloaded operator differ from a built-in operator? In what ways are overloaded operators the same as the built-in operators?\n\n**Differ**\n1. We can call an overloaded operator function directly.\n2. An overloaded operator function must either be a member of a class or have at least one parameter of class type.\n3. A few operators guarantee the order in which operands are evaluated. These overloaded versions of these operators do not preserve order of evaluation and/or short-circuit evaluation, it is usually a bad idea to overload them.\n> In particular, the operand-evaluation guarantees of the logical `AND`, logical `OR`, and comma operators are not preserved, Moreover, overloaded versions of `&&` or `||` operators do not preserve short-circuit evaluation properties of the built-in operators. Both operands are always evaluated.\n\n**Same**\n\n- An overloaded operator has the same precedence and associativity as the corresponding built-in operator.\n\n## Exercise 14.2:\n>Write declarations for the overloaded input, output, addition, and compound-assignment operators for `Sales_data`.\n\n[hpp](ex14_02.h) | [cpp](ex14_02.cpp)\n\n## Exercise 14.3:\n>Both `string` and `vector` define an overloaded == that can be used to compare objects of those types. Assuming `svec1` and `svec2 `are `vectors` that hold `strings`, identify which version of == is applied in each of the following expressions:\n- (a) `\"cobble\" == \"stone\"`\n- (b) `svec1[0] == svec2[0]`\n- (c) `svec1 == svec2`\n- (d) `\"svec1[0] == \"stone\"`\n\n(a) neither. (b) `string` (c) `vector` (d) `string`\n\n-----\n\n**Reference**\n- [Why does the following not invoke the overloaded operator== (const String &, const String &)? “cobble” == “stone”](http://stackoverflow.com/questions/2690737/why-does-the-following-not-invoke-the-overloaded-operator-const-string-con)\n\n## Exercise 14.4:\n>Explain how to decide whether the following should be class members:\n- (a) %\n- (b) %=\n- (c) ++\n- (d) ->\n- (e) <<\n- (f) &&\n- (g) ==\n- (h) ()\n\n(a) symmetric operator. Hence, non-member\n\n(b) changing state of objects. Hence, member\n\n(c) changing state of objects. Hence, member\n\n(d) = () [] -> must be member\n\n(e) non-member\n\n(f) symetric , non-member\n\n(g) symetric , non-member\n\n(h) = () [] -> must be member\n\n## Exercise 14.5:\n>In exercise 7.40 from 7.5.1 (p. 291) you wrote a sketch of one of the following classes. Decide what, if any, overloaded operators your class should provide.\n\nSuch as `Book`\n\n[hpp](ex14_05.h) | [cpp](ex14_05.cpp) | [test](ex14_05_TEST.cpp)\n\n## Exercise 14.6:\n>Define an output operator for your `Sales_data` class.\n\nsee [Exercise 14.2](#exercise-142).\n\n## Exercise 14.7:\n>Define an output operator for you `String` class you wrote for the exercises in 13.5 (p. 531).\n\n[hpp](ex14_07.h) | [cpp](ex14_07.cpp) | [Test](ex14_07_TEST.cpp)\n\n## Exercise 14.8:\n>Define an output operator for the class you chose in exercise 7.40 from 7.5.1 (p. 291).\n\nsee [Exercise 14.5](#exercise-145)\n\n## Exercise 14.9:\n>Define an input operator for your Sales_data class.\n\nsee [Exercise 14.2](#exercise-142).\n\n## Exercise 14.10:\n>Describe the behaviour of the Sales_data input operator if given the following input:\n- (a) 0-201-99999-9 10 24.95\n- (b) 10 24.95 0-210-99999-9\n\n- (a) correct format.\n- (b) ilegal input. But `.95` will be converted to a float stored in this object. As a result, the data inside will be a wrong one.\nOutput: `10 24 22.8 0.95`\n\ncheck [Test](ex14_02_TEST.cpp)\n\n## Exercise 14.11:\n>What, if anything, is wrong with the following Sales_data input operator? What would happen if we gave this operator the data in the previous exercise?\n```cpp\nistream& operator>>(istream& in, Sales_data& s)\n{\n    double price;\n    in >> s.bookNo >> s.units_sold >> price;\n    s.revenue = s.units_sold * price;\n    return in;\n}\n```\n\nno input check. nothing happend.\n\n## Exercise 14.12:\n>Define an input operator for the class you used in exercise 7.40 from 7.5.1 (p. 291). Be sure the operator handles input errors.\n\nsee [Exercise 14.5](#exercise-145)\n\n## Exercise 14.13:\n>Which other arithmetic operators (Table 4.1 (p. 139)), if any, do you think Sales_data ought to support? Define any you think the class should include.\n\nSubstraction, in order to be able to revert a previously addition.\n[hpp](ex14_13.h) | [cpp](ex14_13.cpp) | [Test](ex14_13_TEST.cpp)\n\n## Exercise 14.14:\n>Why do you think it is more efficient to define `operator+` to call `operator+=` rather than the other way around?\n\nDiscussing on [SO](http://stackoverflow.com/questions/21071167/why-is-it-more-efficient-to-define-operator-to-call-operator-rather-than-the).\n\n## Exercise 14.15:\n>Should the class you chose for exercise 7.40 from 7.5.1 (p. 291) define any of the arithmetic operators? If so, implement them. If not, explain why not.\n\n[hpp](ex14_15.h) | [cpp](ex14_15.cpp) | [Test](ex14_15_TEST.cpp)\n\n## Exercise 14.16:\n>Define equality and inequality operators for your `StrBlob` (12.1.1, p. 456), `StrBlobPtr` (12.1.6, p. 474), `StrVec` (13.5, p.526), and `String` (13.5, p. 531) classes.\n\n- `StrBlob` & `StrBlobPtr`: [hpp](ex14_16_StrBlob.h) | [cpp](ex14_16_StrBlob.cpp) | [Test](ex14_16_StrBlobTest.cpp)\n- `StrVec`: [hpp](ex14_16_StrVec.h) | [cpp](ex14_16_StrVec.cpp) | [Test](ex14_16_StrVecMain.cpp)\n- `String`: [hpp](ex14_16_String.h) | [cpp](ex14_16_String.cpp) | [Test](ex14_16_StringMain.cpp)\n\n## Exercise 14.17:\n>Should the class you chose for exercise 7.40 from 7.5.1(p. 291) define the equality operators? If so, implement them. If not, explain why not.\n\nyes.see [Exercise 14.15](#exercise-1415)\n\n## Exercise 14.18:\n>Define relational operators for your `StrBlob`, `StrBlobPtr`, `StrVec`, and `String` classes.\n\n- `StrBlob` & `StrBlobPtr`: [hpp](ex14_18_StrBlob.h) | [cpp](ex14_18_StrBlob.cpp) | [Test](ex14_18_StrBlobTest.cpp)\n- `StrVec`: [hpp](ex14_18_StrVec.h) | [cpp](ex14_18_StrVec.cpp) | [Test](ex14_18_StrVecMain.cpp)\n- `String`: [hpp](ex14_18_String.h) | [cpp](ex14_18_String.cpp) | [Test](ex14_18_StringMain.cpp)\n\n## Exercise 14.19:\n>Should the class you chose for exercise 7.40 from 7.5.1 (p. 291) define the relational operators? If so, implement them. If not, explain why not.\n\nyes.see [Exercise 14.15](#exercise-1415)\n\n## Exercise 14.20:\n>Define the addition and compound-assignment operators for your `Sales_data` class.\n\nsee [Exercise 14.2](#exercise-142).\n\n## Exercise 14.21:\n>Write the `Sales_data` operators so that `+` does the actual addition and `+=` calls `+`. Discuss the disadvantages of this approach compared to the way these operators were defined in 14.3 (p. 560) and 14.4 (p.564).\n\n```cpp\nSales_data& Sales_data::operator+=(const Sales_data &rhs)\n{\n    Sales_data old_data = *this;\n    *this = old_data + rhs;\n    return *this;\n}\n\nSales_data operator+(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum;\n    sum.units_sold = lhs.units_sold + rhs.units_sold;\n    sum.revenue = lhs.revenue + rhs.revenue;\n    return sum;\n}\n```\n\n**Disadvantages**: Both `+` and `+=`, uses an temporary object of `Sales_data`. But it is no need for that.\n\n## Exercise 14.22:\n>Define a version of the assignment operator that can assign a `string` representing an ISBN to a `Sales_data`.\n\n[hpp](ex14_22.h) | [cpp](ex14_22.cpp) | [Test](ex14_22_TEST.cpp)\n\n## Exercise 14.23:\n>Define an initializer_list assignment operator for your version of the `StrVec` class.\n\n[hpp](ex14_23.h) | [cpp](ex14_23.cpp) | [Test](ex14_23_TEST.cpp)\n\n## Exercise 14.24:\n>Decide whether the class you used in exercise 7.40 from 7.5.1 (p. 291) needs a copy- and move-assignment operator. If so, define those operators.\n\n[hpp](ex14_24.h) | [cpp](ex14_24.cpp) | [Test](ex14_24_TEST.cpp)\n\n## Exercise 14.25:\n>Implement any other assignment operators your class should define. Explain which types should be used as operands and why.\n\nsee [Exercise 14.24](#exercise-1424)\n\n## Exercise 14.26:\n>Define subscript operators for your `StrVec`, `String`, `StrBlob`, and `StrBlobPtr` classes.\n\n- `StrBlob` & `StrBlobPtr`: [hpp](ex14_26_StrBlob.h) | [cpp](ex14_26_StrBlob.cpp) | [Test](ex14_26_StrBlobTest.cpp)\n- `StrVec`: [hpp](ex14_26_StrVec.h) | [cpp](ex14_26_StrVec.cpp) | [Test](ex14_26_StrVecMain.cpp)\n- `String`: [hpp](ex14_26_String.h) | [cpp](ex14_26_String.cpp) | [Test](ex14_26_StringMain.cpp)\n\n## Exercise 14.27:\n> Add increment and decrement operators to your `StrBlobPtr` class.\n\n[hpp](ex14_27_28_StrBlob.h) | [cpp](ex14_27_28_StrBlob.cpp) | [Test](ex14_27_28_StrBlobTest.cpp)\n\n## Exercise 14.28:\n> Define addition and subtraction for `StrBlobPtr` so that these operators implement pointer arithmetic (3.5.3, p. 119).\n\nsee [Exercise 14.27](#exercise-1427)\n\n## Exercise 14.29:\n> We did not define a `const` version of the increment and decrement operators. Why not?\n\nBecause `++` and `--` change the state of the object. Hence , it's meaningless to do so.\n\n## Exercise 14.30:\n> Add dereference and arrow operators to your `StrBlobPtr` class and to the `ConstStrBlobPtr` class that you defined in exercise 12.22 from 12.1.6 (p. 476). Note that the operators in `constStrBlobPtr` must return `const` references because the `data` member in `constStrBlobPtr` points to a `const vector`.\n\n[hpp](ex14_30_StrBlob.h) | [cpp](ex14_30_StrBlob.cpp) | [Test](ex14_30_StrBlobTest.cpp)\n\n## Exercise 14.31:\n> Our StrBlobPtr class does not define the copy constructor, assignment operator, or a destructor. Why is that okay?\n\nApplying the Rule of 3/5:\nThere is no dynamic allocation to deal with, so the synthesized destructor is enough. Moreover, no unique is needed. Hence, the synthesized ones can handle all the corresponding operations.\n\n## Exercise 14.32:\n> Define a class that holds a pointer to a `StrBlobPtr`. Define the overloaded arrow operator for that class.\n\n[hpp](ex14_32.h) | [cpp](ex14_32.cpp)\n\n## Exercise 14.33:\n> How many operands may an overloaded function-call operator take?\n\nAn overloaded operator function has the same number of parameters as the operator has operands. Hence the maximum value should be around 256.\n([question on SO](http://stackoverflow.com/questions/21211889/how-many-operands-may-an-overloaded-function-call-operator-take))\n\n## Exercise 14.34:\n> Define a function-object class to perform an if-then-else operation: The call operator for this class should take three parameters. It should test its first parameter and if that test succeeds, it should return its second parameter; otherwise, it should return its third parameter.\n\n```cpp\nstruct Test {\n    int operator()(bool b, int iA, int iB) {\n        return b ? iA : iB;\n    }\n};\n```\n\n## Exercise 14.35:\n> Write a class like `PrintString` that reads a line of input from an `istream` and returns a `string` representing what was read. If the read fails, return the empty `string`.\n\n[Test](ex14_35.cpp)\n\n## Exercise 14.36:\n> Use the class from the previous exercise to read the standard input, storing each line as an element in a vector.\n\n[Test](ex14_36.cpp)\n\n## Exercise 14.37:\n> Write a class that tests whether two values are equal. Use that object and the library algorithms to write a program to replace all instances of a given value in a sequence.\n\n[Test](ex14_37.cpp)\n\n## Exercise 14.38:\n> Write a class that tests whether the length of a given `string` matches a given bound. Use that object to write a program to report how many words in an input file are of sizes 1 through 10 inclusive.\n\n[BoundTest](ex14_38_39.cpp)\n\n## Exercise 14.39:\n> Revise the previous program to report the count of words that are sizes 1 through 9 and 10 or more.\n\nsee [Exercise 14.38](#exercise-1438)\n\n## Exercise 14.40:\n> Rewrite the `biggies` function from 10.3.2 (p. 391) to use function-object classes in place of lambdas.\n\n[Test](ex14_40.cpp)\n\n## Exercise 14.41:\n> Why do you suppose the new standard added lambdas? Explain when you would use a lambda and when you would write a class instead.\n\nIMO, lambda is quite handy to use. Lambda can be used when the functor is not used frequently nor complicated, whereas functor is supposed to call more times than lambda or quite complicated to implement as a lambda.\n\n## Exercise 14.42:\n> Using library function objects and adaptors, define an expression to\n- (a) Count the number of values that are greater than 1024\n- (b) Find the first string that is not equal to `pooh`\n- (c) Multiply all values by 2\n\n```cpp\nstd::count_if(ivec.cbegin(), ivec.cend(), std::bind(std::greater<int>(), _1, 1024));\nstd::find_if(svec.cbegin(), svec.cend(), std::bind(std::not_equal_to<std::string>(), _1, \"pooh\"));\nstd::transform(ivec.begin(), ivec.end(), ivec.begin(), std::bind(std::multiplies<int>(), _1, 2));\n```\n\n[Test](ex14_42.cpp)\n\n## Exercise 14.43:\n> Using library function objects, determine whether a given `int` value is divisible by any element in a container of `int`s.\n\n[ex14_43.cpp](ex14_43.cpp)\n\n## Exercise 14.44:\n> Write your own version of a simple desk calculator that can handle binary operations.\n\n[ex14_44.cpp](ex14_44.cpp)\n\n## Exercise 14.45:\n> Write conversion operators to convert a `Sales_data` to `string` and to `double`. What values do you think these operators should return?\n\n[hpp](ex14_45.h) | [cpp](ex14_45.cpp) | [Test](ex14_45_TEST.cpp)\n\n## Exercise 14.46:\n> Explain whether defining these Sales_data conversion operators is a good idea and whether they should be explicit.\n\nIt's a bad idea to do so, because these conversion is misleading.`explicit` should be added to prevent implicit conversion.\n\n## Exercise 14.47:\n> Explain the difference between these two conversion operators:\n```cpp\nstruct Integral {\n    operator const int();   // meaningless, it will be ignored by compiler.\n    operator int() const;   // promising that this operator will not change the state of the obj\n};\n```\n\n## Exercise 14.48:\n> Determine whether the class you used in exercise 7.40 from 7.5.1 (p. 291) should have a conversion to `bool`. If so, explain why, and explain whether the operator should be `explicit`. If not, explain why not.\n\nA conversion to bool can be useful for the class Date. But it must be an explicit one to prevent any automatic conversion.\n\n## Exercise 14.49:\n> Regardless of whether it is a good idea to do so, define a conversion to bool for the class from the previous exercise.\n\n[hpp](ex14_49.h) | [cpp](ex14_49.cpp) | [Test](ex14_49_TEST.cpp)\n\n## Exercise 14.50:\n> Show the possible class-type conversion sequences for the initializations of ex1 and ex2. Explain whether the initializations are legal or not.\n```cpp\nstruct LongDouble {\n    LongDouble(double = 0.0);\n    operator double();\n    operator float();\n};\nLongDouble ldObj;\nint ex1 = ldObj;    // error ambiguous: double or float?\nfloat ex2 = ldObj;  // legal\n```\n\n## Exercise 14.51:\n> Show the conversion sequences (if any) needed to call each version of `calc` and explain why the best viable function is selected.\n```cpp\nvoid calc(int);\nvoid calc(LongDouble);\ndouble dval;\ncalc(dval); // which calc?\n```\n\nbest viable function: `void calc(int)`. cause class-type conversion is the lowest ranked.\n\nreview the order:\n\n1. exact match\n2. const conversion\n3. promotion\n4. arithmetic or pointer conversion\n5. class-type conversion\n\n## Exercise 14.52:\n> Which `operator+`, if any, is selected for each of the addition expressions? List the candidate functions, the viable functions, and the type conversions on the arguments for each viable function:\n```cpp\nstruct LongDouble {\n    // member operator+ for illustration purposes; + is usually a nonmember LongDouble operator+(const SmallInt&); // 1\n    // other members as in 14.9.2 (p. 587)\n};\nLongDouble operator+(LongDouble&, double); // 2\nSmallInt si;\nLongDouble ld;\nld = si + ld;\nld = ld + si;\n```\n\n`ld = si + ld;` is ambiguous. `ld = ld + si` can use both 1 and 2, but 1 is more exactly. (in the 2, SmallInt need to convert to `double`)\n\n\n## Exercise 14.53:\n> Given the definition of SmallInt on page 588, determine whether the following addition expression is legal. If so, what addition operator is used? If not, how might you change the code to make it legal?\n```cpp\nSmallInt s1;\ndouble d = s1 + 3.14;\n```\n\nambiguous.\n\n**Fixed**:\n```cpp\nSmallInt s1;\ndouble d = s1 + SmallInt(3.14);\n```\n"
  },
  {
    "path": "ch14/ex14_02.cpp",
    "content": "//\n//  ex14_02.cpp\n//  Exercise 14.2\n//\n//  Created by pezy on 3/9/15.\n//\n//  @Brief implementation of class Sales_data\n//  @See ex14_02.h\n\n#include \"ex14_02.h\"\n\nSales_data::Sales_data(std::istream &is) : Sales_data()\n{\n    is >> *this;\n}\n\nSales_data& Sales_data::operator+=(const Sales_data &rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\nstd::istream& operator>>(std::istream &is, Sales_data &item)\n{\n    double price = 0.0;\n    is >> item.bookNo >> item.units_sold >> price;\n    if (is)\n        item.revenue = price * item.units_sold;\n    else\n        item = Sales_data();\n    return is;\n}\n\nstd::ostream& operator<<(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue << \" \" << item.avg_price();\n    return os;\n}\n\nSales_data operator+(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum += rhs;\n    return sum;\n}\n"
  },
  {
    "path": "ch14/ex14_02.h",
    "content": "//\n//  ex14_02.h\n//  Exercise 14.2\n//\n//  Created by pezy on 3/9/15.\n//\n//  @See ex7_41.h\n//  @Add overloaded input, output, addition, and compound-assignment operators\n\n#ifndef CP5_CH14_EX14_02_H\n#define CP5_CH14_EX14_02_H\n\n#include <string>\n#include <iostream>\n\nclass Sales_data {\n    friend std::istream& operator>>(std::istream&, Sales_data&); // input\n    friend std::ostream& operator<<(std::ostream&, const Sales_data&); // output\n    friend Sales_data operator+(const Sales_data&, const Sales_data&); // addition\n\npublic:\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data() : Sales_data(\"\", 0, 0.0f){ }\n    Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f){ }\n    Sales_data(std::istream &is);\n\n    Sales_data& operator+=(const Sales_data&); // compound-assignment\n    std::string isbn() const { return bookNo; }\n\nprivate:\n    inline double avg_price() const;\n\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nstd::istream& operator>>(std::istream&, Sales_data&);\nstd::ostream& operator<<(std::ostream&, const Sales_data&);\nSales_data operator+(const Sales_data&, const Sales_data&);\n\ninline double Sales_data::avg_price() const\n{\n    return units_sold ? revenue/units_sold : 0;\n}\n\n#endif // CP5_CH14_EX14_02_H\n"
  },
  {
    "path": "ch14/ex14_02_TEST.cpp",
    "content": "#include \"ex14_02.h\"\n\nint main()\n{\n    Sales_data cp5;\n    std::cin >> cp5;\n    std::cout << cp5 << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_05.cpp",
    "content": "#include \"ex14_05.h\"\n\nstd::istream& operator>>(std::istream &in, Book &book)\n{\n    in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;\n    return in;\n}\n\nstd::ostream& operator<<(std::ostream &out, const Book &book)\n{\n    out << book.no_ << \" \" << book.name_ << \" \" << book.author_ << \" \" << book.pubdate_;\n    return out;\n}\n\nbool operator==(const Book &lhs, const Book &rhs)\n{\n    return lhs.no_ == rhs.no_;\n}\n\nbool operator!=(const Book &lhs, const Book &rhs)\n{\n    return !(lhs == rhs);\n}\n"
  },
  {
    "path": "ch14/ex14_05.h",
    "content": "#ifndef CP5_CH14_EX14_05_H\n#define CP5_CH14_EX14_05_H\n\n#include <iostream>\n#include <string>\n\nclass Book {\n    friend std::istream& operator>>(std::istream&, Book&);\n    friend std::ostream& operator<<(std::ostream&, const Book&);\n    friend bool operator==(const Book&, const Book&);\n    friend bool operator!=(const Book&, const Book&);\n\npublic:\n    Book() = default;\n    Book(unsigned no, std::string name, std::string author, std::string pubdate):no_(no), name_(name), author_(author), pubdate_(pubdate) { }\n    Book(std::istream &in) { in >> *this; }\n\nprivate:\n    unsigned no_;\n    std::string name_;\n    std::string author_;\n    std::string pubdate_;\n};\n\nstd::istream& operator>>(std::istream&, Book&);\nstd::ostream& operator<<(std::ostream&, const Book&);\nbool operator==(const Book&, const Book&);\nbool operator!=(const Book&, const Book&);\n\n\n#endif // CP5_CH14_EX14_05_H\n"
  },
  {
    "path": "ch14/ex14_05_TEST.cpp",
    "content": "#include \"ex14_05.h\"\n\nint main()\n{\n    Book book1(123, \"CP5\", \"Lippman\", \"2012\");\n    Book book2(123, \"CP5\", \"Lippman\", \"2012\");\n\n    if (book1 == book2)\n        std::cout << book1 << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_07.cpp",
    "content": "#include \"ex14_07.h\"\n#include <algorithm>\n#include <iostream>\n\nstd::pair<char*, char*>\nString::alloc_n_copy(const char *b, const char *e)\n{\n    auto str = alloc.allocate(e - b);\n    return{ str, std::uninitialized_copy(b, e, str) };\n}\n\nvoid String::range_initializer(const char *first, const char *last)\n{\n    auto newstr = alloc_n_copy(first, last);\n    elements = newstr.first;\n    end = newstr.second;\n}\n\nString::String(const char *s)\n{\n    char *sl = const_cast<char*>(s);\n    while (*sl)\n        ++sl;\n    range_initializer(s, ++sl);\n}\n\nString::String(const String& rhs)\n{\n    range_initializer(rhs.elements, rhs.end);\n    std::cout << \"copy constructor\" << std::endl;\n}\n\nvoid String::free()\n{\n    if (elements) {\n        std::for_each(elements, end, [this](char &c){ alloc.destroy(&c); });\n        alloc.deallocate(elements, end - elements);\n    }\n}\n\nString::~String()\n{\n    free();\n}\n\nString& String::operator = (const String &rhs)\n{\n    auto newstr = alloc_n_copy(rhs.elements, rhs.end);\n    free();\n    elements = newstr.first;\n    end = newstr.second;\n    std::cout << \"copy-assignment\" << std::endl;\n    return *this;\n}\n\nstd::ostream& operator<<(std::ostream &os, const String &s)\n{\n    char *c = const_cast<char*>(s.c_str());\n    while (*c)\n        os << *c++;\n    return os;\n}\n"
  },
  {
    "path": "ch14/ex14_07.h",
    "content": "#ifndef CP5_CH14_EX07_H_\n#define CP5_CH14_EX07_H_\n\n#include <memory>\n#include <iostream>\n\nclass String\n{\n    friend std::ostream& operator<<(std::ostream&, const String&);\npublic:\n    String() : String(\"\") { }\n    String(const char *);\n    String(const String&);\n    String& operator=(const String&);\n    ~String();\n\n    const char *c_str() const { return elements; }\n    size_t size() const { return end - elements; }\n    size_t length() const { return end - elements - 1; }\n\nprivate:\n    std::pair<char*, char*> alloc_n_copy(const char*, const char*);\n    void range_initializer(const char*, const char*);\n    void free();\n\nprivate:\n    char *elements;\n    char *end;\n    std::allocator<char> alloc;\n};\n\nstd::ostream& operator<<(std::ostream&, const String&);\n\n#endif //CP5_CH14_EX07_H_\n"
  },
  {
    "path": "ch14/ex14_07_TEST.cpp",
    "content": "#include \"ex14_07.h\"\n\nint main()\n{\n    String str(\"Hello World\");\n    std::cout << str << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_13.cpp",
    "content": "//\n//  ex14_13.cpp\n//  Exercise 14.13\n//\n//  Created by pezy on 3/9/15.\n//  Substraction and compound-substraction operations added by hoeselm on 4/10/16.\n//\n//  @Brief implementation of class Sales_data\n//  @See ex14_13.h\n\n#include \"ex14_13.h\"\n\nSales_data::Sales_data(std::istream &is) : Sales_data()\n{\n    is >> *this;\n}\n\nSales_data& Sales_data::operator+=(const Sales_data &rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\n\nSales_data& Sales_data::operator-=(const Sales_data &rhs)\n{\n    units_sold -= rhs.units_sold;\n    revenue -= rhs.revenue;\n    return *this;\n}\n\nstd::istream& operator>>(std::istream &is, Sales_data &item)\n{\n    double price = 0.0;\n    is >> item.bookNo >> item.units_sold >> price;\n    if (is)\n        item.revenue = price * item.units_sold;\n    else\n        item = Sales_data();\n    return is;\n}\n\nstd::ostream& operator<<(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue << \" \" << item.avg_price();\n    return os;\n}\n\nSales_data operator+(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum += rhs;\n    return sum;\n}\n\nSales_data operator-(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum -= rhs;\n    return sum;\n}\n"
  },
  {
    "path": "ch14/ex14_13.h",
    "content": "//\n//  ex14_13.h\n//  Exercise 14.13\n//\n//  Created by pezy on 3/9/15.\n//  Substraction and compound-substraction operations added by hoeselm on 4/10/16.\n//\n//  @See ex7_41.h\n//  @Add overloaded input, output, addition, and compound-assignment operators\n\n#ifndef CP5_CH14_EX14_13_H\n#define CP5_CH14_EX14_13_H\n\n#include <string>\n#include <iostream>\n\nclass Sales_data {\n    friend std::istream& operator>>(std::istream&, Sales_data&); // input\n    friend std::ostream& operator<<(std::ostream&, const Sales_data&); // output\n    friend Sales_data operator+(const Sales_data&, const Sales_data&); // addition\n    friend Sales_data operator-(const Sales_data&, const Sales_data&); // substraction\n\npublic:\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data() : Sales_data(\"\", 0, 0.0f){ }\n    Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f){ }\n    Sales_data(std::istream &is);\n\n    Sales_data& operator+=(const Sales_data&); // compound-assignment\n    Sales_data& operator-=(const Sales_data&); // compound-substraction\n    std::string isbn() const { return bookNo; }\n\nprivate:\n    inline double avg_price() const;\n\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nstd::istream& operator>>(std::istream&, Sales_data&);\nstd::ostream& operator<<(std::ostream&, const Sales_data&);\nSales_data operator+(const Sales_data&, const Sales_data&);\nSales_data operator-(const Sales_data&, const Sales_data&);\n\ninline double Sales_data::avg_price() const\n{\n    return units_sold ? revenue/units_sold : 0;\n}\n\n#endif // CP5_CH14_EX14_13_H\n"
  },
  {
    "path": "ch14/ex14_13_TEST.cpp",
    "content": "#include \"ex14_13.h\"\n\nint main()\n{\n  Sales_data s1(\"book1\", 150, 10);\n  Sales_data s2(\"book1\", 200, 20);\n\n  std::cout << s1 << std::endl;\n\n  // Assignment\n  s1 = s1 + s2;\n  std::cout << s1 << std::endl;\n\n  // Compound assignment\n  s1 += s2;\n  std::cout << s1 << std::endl;\n\n  // Compound substraction\n  s1 -= s2;\n  std::cout << s1 << std::endl;\n\n  // Substraction\n  s1 = s1 - s2;\n  std::cout << s1 << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_15.cpp",
    "content": "#include \"ex14_15.h\"\n\nstd::istream& operator>>(std::istream &in, Book &book)\n{\n    in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_ >> book.number_;\n    return in;\n}\n\nstd::ostream& operator<<(std::ostream &out, const Book &book)\n{\n    out << book.no_ << \" \" << book.name_ << \" \" << book.author_ << \" \" << book.pubdate_ << \" \" << book.number_ << std::endl;\n    return out;\n}\n\nbool operator==(const Book &lhs, const Book &rhs)\n{\n    return lhs.no_ == rhs.no_;\n}\n\nbool operator!=(const Book &lhs, const Book &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator<(const Book &lhs, const Book &rhs)\n{\n    return lhs.no_ < rhs.no_;\n}\n\nbool operator>(const Book &lhs, const Book &rhs)\n{\n    return rhs < lhs;\n}\n\nBook& Book::operator+=(const Book &rhs)\n{\n    if (rhs == *this)\n        this->number_ += rhs.number_;\n\n    return *this;\n}\n\nBook operator+(const Book &lhs, const Book &rhs)\n{\n    Book book = lhs;\n    book += rhs;\n    return book;\n}\n"
  },
  {
    "path": "ch14/ex14_15.h",
    "content": "#ifndef CP5_CH14_EX14_15_H_\n#define CP5_CH14_EX14_15_H_\n\n#include <iostream>\n#include <string>\n\nclass Book {\n    friend std::istream& operator>>(std::istream&, Book&);\n    friend std::ostream& operator<<(std::ostream&, const Book&);\n    friend bool operator==(const Book&, const Book&);\n    friend bool operator!=(const Book&, const Book&);\n    friend bool operator<(const Book&, const Book&);\n    friend bool operator>(const Book&, const Book&);\n    friend Book operator+(const Book&, const Book&);\n\npublic:\n    Book() = default;\n    Book(unsigned no, std::string name, std::string author, std::string pubdate, unsigned number):no_(no), name_(name), author_(author), pubdate_(pubdate), number_(number) { }\n    Book(std::istream &in) { in >> *this; }\n\n    Book& operator+=(const Book&);\n\nprivate:\n    unsigned no_;\n    std::string name_;\n    std::string author_;\n    std::string pubdate_;\n    unsigned number_;\n};\n\nstd::istream& operator>>(std::istream&, Book&);\nstd::ostream& operator<<(std::ostream&, const Book&);\nbool operator==(const Book&, const Book&);\nbool operator!=(const Book&, const Book&);\nbool operator<(const Book&, const Book&);\nbool operator>(const Book&, const Book&);\nBook operator+(const Book&, const Book&);\n\n#endif // CP5_CH14_EX14_15_H_\n"
  },
  {
    "path": "ch14/ex14_15_TEST.cpp",
    "content": "#include \"ex14_15.h\"\n\nint main()\n{\n    Book cp5_1(12345, \"CP5\", \"Lippmen\", \"2012\", 2);\n    Book cp5_2(12345, \"CP5\", \"Lippmen\", \"2012\", 4);\n\n    std::cout << cp5_1 + cp5_2 << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_16_StrBlob.cpp",
    "content": "#include \"ex14_16_StrBlob.h\"\n\n//==================================================================\n//\n//\t\toperators\n//\n//==================================================================\n\nbool operator==(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return *lhs.data == *rhs.data;\n}\n\nbool operator!=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\n//==================================================================\n//\n//\t\tcopy assignment operator and move assignment operator.\n//\n//==================================================================\n\nStrBlob& StrBlob::operator=(const StrBlob &lhs)\n{\n    data = make_shared<vector<string>>(*lhs.data);\n    return *this;\n}\n\nStrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        data = std::move(rhs.data);\n        rhs.data = nullptr;\n    }\n\n    return *this;\n}\n\n//==================================================================\n//\n//\t\tmembers\n//\n//==================================================================\n\nStrBlobPtr StrBlob::begin()\n{\n    return StrBlobPtr(*this);\n}\n\nStrBlobPtr StrBlob::end()\n{\n    return StrBlobPtr(*this, data->size());\n}\n\nConstStrBlobPtr StrBlob::cbegin() const\n{\n    return ConstStrBlobPtr(*this);\n}\n\nConstStrBlobPtr StrBlob::cend() const\n{\n    return ConstStrBlobPtr(*this, data->size());\n}\n"
  },
  {
    "path": "ch14/ex14_16_StrBlob.h",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nStrBlob, StrBlobPtr, ConstStrBlobPtr\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#ifndef CP5_STRBLOB_H_\n#define CP5_STRBLOB_H_\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <initializer_list>\nusing std::initializer_list;\n\n#include <memory>\nusing std::make_shared; using std::shared_ptr;\n\n#include <exception>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrBlobPtr;\nclass ConstStrBlobPtr;\n\n//=================================================================================\n//\n//\t\tStrBlob - custom vector<string>\n//\n//=================================================================================\n\nclass StrBlob {\n    using size_type = vector<string>::size_type;\n    friend class ConstStrBlobPtr;\n    friend class StrBlobPtr;\n    friend bool operator==(const StrBlob&, const StrBlob&);\n    friend bool operator!=(const StrBlob&, const StrBlob&);\n\npublic:\n    StrBlob() : data(make_shared<vector<string>>()) { }\n    StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) { }\n\n    StrBlob(const StrBlob &sb) : data(make_shared<vector<string>>(*sb.data)) { }\n    StrBlob& operator=(const StrBlob&);\n\n    StrBlob(StrBlob &&rhs) NOEXCEPT : data(std::move(rhs.data)) { }\n    StrBlob& operator=(StrBlob &&)NOEXCEPT;\n\n    StrBlobPtr begin();\n    StrBlobPtr end();\n\n    ConstStrBlobPtr cbegin() const;\n    ConstStrBlobPtr cend() const;\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void push_back(string &&s) { data->push_back(std::move(s)); }\n\n    void pop_back();\n    string& front();\n    string& back();\n    const string& front() const;\n    const string& back() const;\n\nprivate:\n    void check(size_type, const string&) const;\n\n    shared_ptr<vector<string>> data;\n};\n\nbool operator==(const StrBlob&, const StrBlob&);\nbool operator!=(const StrBlob&, const StrBlob&);\n\ninline void StrBlob::pop_back()\n{\n    check(0, \"pop_back on empty StrBlob\");\n    data->pop_back();\n}\n\ninline string& StrBlob::front()\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline string& StrBlob::back()\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline const string& StrBlob::front() const\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline const string& StrBlob::back() const\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline void StrBlob::check(size_type i, const string &msg) const\n{\n    if (i >= data->size()) throw std::out_of_range(msg);\n}\n\n//=================================================================================\n//\n//\t\tStrBlobPtr - custom iterator of StrBlob\n//\n//=================================================================================\n\nclass StrBlobPtr {\n    friend bool operator==(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator!=(const StrBlobPtr&, const StrBlobPtr&);\npublic:\n    StrBlobPtr() : curr(0) { }\n    StrBlobPtr(StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    string& deref() const;\n    StrBlobPtr& incr();\n\nprivate:\n    shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const StrBlobPtr&, const StrBlobPtr&);\nbool operator!=(const StrBlobPtr&, const StrBlobPtr&);\n\ninline string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline StrBlobPtr& StrBlobPtr::incr()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\n//=================================================================================\n//\n//\t\tConstStrBlobPtr - custom const_iterator of StrBlob\n//\n//=================================================================================\n\nclass ConstStrBlobPtr {\n    friend bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\npublic:\n    ConstStrBlobPtr() : curr(0) { }\n    ConstStrBlobPtr(const StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    const string& deref() const;\n    ConstStrBlobPtr& incr();\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\ninline const string& ConstStrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::incr()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\nbool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\n#endif //CP5_STRBLOB_H_\n"
  },
  {
    "path": "ch14/ex14_16_StrBlobTest.cpp",
    "content": "#include \"ex14_16_StrBlob.h\"\n#include <iostream>\n\nint main()\n{\n    StrBlob sb{ \"Hello\", \"World\", \"Pezy\" };\n\n    for (ConstStrBlobPtr iter = sb.cbegin(); iter != sb.cend(); iter.incr()) {\n        std::cout << iter.deref() << \" \";\n    }\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_16_StrVec.cpp",
    "content": "//\n//  ex13_39.cpp\n//  Exercise 13.39\n//\n//  Created by pezy on 2/3/15.\n//\n//  Write your own version of StrVec, including versions of\n//  reserve, capacity (9.4, p. 356), and resize (9.3.5, p. 352).\n//\n\n#include \"ex13_39.h\"\n\nvoid StrVec::push_back(const std::string &s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n    auto data = alloc.allocate(e - b);\n    return{ data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n    if (elements) {\n        for (auto p = first_free; p != elements;)\n            alloc.destroy(--p);\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n    auto newdata = alloc_n_copy(rhs.begin(), rhs.end());\n    elements = newdata.first;\n    first_free = cap = newdata.second;\n}\n\nStrVec::~StrVec()\n{\n    free();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n    auto data = alloc_n_copy(rhs.begin(), rhs.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n    auto newcapacity = size() ? 2 * size() : 1;\n    alloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n    resize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i)\n            alloc.construct(first_free++, s);\n    }\n    else if (count < size()) {\n        while (first_free != elements + count)\n            alloc.destroy(--first_free);\n    }\n}\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch14/ex14_16_StrVec.h",
    "content": "#ifndef CP5_STRVEC_H_\n#define CP5_STRVEC_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrVec\n{\n    friend bool operator==(const StrVec&, const StrVec&);\n    friend bool operator!=(const StrVec&, const StrVec&);\n\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(std::initializer_list<std::string>);\n    StrVec(const StrVec&);\n    StrVec& operator=(const StrVec&);\n    StrVec(StrVec&&) NOEXCEPT;\n    StrVec& operator=(StrVec&&)NOEXCEPT;\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    std::string& at(size_t pos) { return *(elements + pos); }\n    const std::string& at(size_t pos) const { return *(elements + pos); }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\nbool operator==(const StrVec&, const StrVec&);\nbool operator!=(const StrVec&, const StrVec&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_16_StrVecMain.cpp",
    "content": "#include \"ex14_16_StrVec.h\"\n#include <iostream>\n#include <vector>\n\nint main()\n{\n    StrVec vec;\n    vec.reserve(6);\n    std::cout << \"capacity(reserve to 6): \" << vec.capacity() << std::endl;\n\n    vec.reserve(4);\n    std::cout << \"capacity(reserve to 4): \" << vec.capacity() << std::endl;\n\n    vec.push_back(\"hello\");\n    vec.push_back(\"world\");\n\n    vec.resize(4);\n\n    for (auto i = vec.begin(); i != vec.end(); ++i)\n        std::cout << *i << std::endl;\n    std::cout << \"-EOF-\" << std::endl;\n\n    vec.resize(1);\n\n    for (auto i = vec.begin(); i != vec.end(); ++i)\n        std::cout << *i << std::endl;\n    std::cout << \"-EOF-\" << std::endl;\n\n    StrVec vec_list{ \"hello\", \"world\", \"pezy\" };\n\n    for (auto i = vec_list.begin(); i != vec_list.end(); ++i)\n        std::cout << *i << \" \";\n    std::cout << std::endl;\n\n    // Test operator==\n\n    const StrVec const_vec_list{ \"hello\", \"world\", \"pezy\" };\n    if (vec_list == const_vec_list)\n        for (const auto &str : const_vec_list)\n            std::cout << str << \" \";\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_16_String.cpp",
    "content": "#include \"ex14_16_String.h\"\n#include <algorithm>\n\n//===========================================================================\n//\n//\t\toperator - friend\n//\n//===========================================================================\n\nstd::ostream& operator<<(std::ostream &os, const String &lhs)\n{\n    os << lhs.c_str();\n    return os;\n}\n\nstd::istream& operator>>(std::istream &is, String &rhs)\n{\n    for (char c; (c = is.get()) != '\\n';) {\n        rhs.push_back(c);\n    }\n    return is;\n}\n\nbool operator==(const String &lhs, const String &rhs)\n{\n    return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));\n}\n\nbool operator!=(const String &lhs, const String &rhs)\n{\n    return !(lhs == rhs);\n}\n\n//===========================================================================\n//\n//\t\tConstructors\n//\n//===========================================================================\n\nString::String(const char *s)\n{\n    char *sl = const_cast<char*>(s);\n    while (*sl)\n        ++sl;\n    range_initializer(s, ++sl);\n}\n\n//===========================================================================\n//\n//\t\tBig 5\n//\n//===========================================================================\n\nString::String(const String& rhs)\n{\n    range_initializer(rhs.elements, rhs.first_free);\n}\n\nString& String::operator = (const String &rhs)\n{\n    auto newstr = alloc_n_copy(rhs.elements, rhs.first_free);\n    free();\n    elements = newstr.first;\n    first_free = cap = newstr.second;\n    last_elem = first_free - 1;\n    return *this;\n}\n\nString::String(String &&s) NOEXCEPT : elements(s.elements), last_elem(s.last_elem), first_free(s.first_free), cap(s.cap)\n{\n    s.elements = s.last_elem = s.first_free = s.cap = nullptr;\n}\n\nString& String::operator = (String &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        free();\n        elements = rhs.elements;\n        last_elem = rhs.last_elem;\n        first_free = rhs.first_free;\n        cap = rhs.cap;\n        rhs.elements = rhs.last_elem = rhs.first_free = rhs.cap = nullptr;\n    }\n    return *this;\n}\n\nString::~String()\n{\n    free();\n}\n\n//===========================================================================\n//\n//\t\tmembers\n//\n//===========================================================================\n\nvoid String::push_back(const char c)\n{\n    chk_n_alloc();\n    *last_elem = c;\n    last_elem = first_free;\n    alloc.construct(first_free++, '\\0');\n}\n\nvoid String::reallocate()\n{\n    //\t\\0    |    -\n    //  ^          ^\n    // elements    first_free\n    // last_elem   cap\n\n    auto newcapacity = size() ? 2 * (size() + 1) : 2;\n    alloc_n_move(newcapacity);\n}\n\nvoid String::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size() + 1; ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    last_elem = dest - 1;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid String::free()\n{\n    if (elements) {\n        std::for_each(elements, first_free, [this](char &c){ alloc.destroy(&c); });\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nstd::pair<char*, char*>\nString::alloc_n_copy(const char *b, const char *e)\n{\n    auto str = alloc.allocate(e - b);\n    return{ str, std::uninitialized_copy(b, e, str) };\n}\n\nvoid String::range_initializer(const char *first, const char *last)\n{\n    auto newstr = alloc_n_copy(first, last);\n    elements = newstr.first;\n    first_free = cap = newstr.second;\n    last_elem = first_free - 1;\n}\n\nvoid String::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid String::resize(size_t count, char c)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i) {\n            *last_elem++ = c;\n            alloc.construct(first_free++, '\\0');\n        }\n\n    }\n    else if (count < size()) {\n        while (last_elem != elements + count) {\n            --last_elem;\n            alloc.destroy(--first_free);\n        }\n        *last_elem = '\\0';\n    }\n}\n\nvoid String::resize(size_t count)\n{\n    resize(count, ' ');\n}\n"
  },
  {
    "path": "ch14/ex14_16_String.h",
    "content": "#ifndef CP5_STRING_H__\n#define CP5_STRING_H__\n\n#include <memory>\n#include <iostream>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass String\n{\n    friend std::ostream& operator<<(std::ostream&, const String&);\n    friend std::istream& operator>>(std::istream&, String&);\n    friend bool operator==(const String&, const String&);\n    friend bool operator!=(const String&, const String&);\n\npublic:\n    String() : String(\"\") { }\n    String(const char *);\n    String(const String&);\n    String& operator=(const String&);\n    String(String &&) NOEXCEPT;\n    String& operator=(String&&)NOEXCEPT;\n    ~String();\n\n    void push_back(const char);\n\n    char* begin() const { return elements; }\n    char* end() const { return last_elem; }\n\n    const char *c_str() const { return elements; }\n    size_t size() const { return last_elem - elements; }\n    size_t length() const { return size(); }\n    size_t capacity() const { return cap - elements; }\n\n    void reserve(size_t);\n    void resize(size_t);\n    void resize(size_t, char);\n\nprivate:\n    std::pair<char*, char*> alloc_n_copy(const char*, const char*);\n    void range_initializer(const char*, const char*);\n    void free();\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void chk_n_alloc() { if (first_free == cap) reallocate(); }\n\nprivate:\n    char *elements;\n    char *last_elem;\n    char *first_free;\n    char *cap;\n    std::allocator<char> alloc;\n};\n\nstd::ostream& operator<<(std::ostream&, const String&);\nstd::istream& operator>>(std::istream&, String&);\nbool operator==(const String&, const String&);\nbool operator!=(const String&, const String&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_16_StringMain.cpp",
    "content": "#include \"ex14_16_String.h\"\n#include <vector>\n#include <iostream>\n#include <algorithm>\n#include <iterator>\n#include <string>\n\nvoid foo(String x)\n{\n    std::cout << x << std::endl;\n}\n\nvoid bar(const String& x)\n{\n    std::cout << x.c_str() << std::endl;\n}\n\nString baz()\n{\n    String ret(\"world\");\n    return ret;\n}\n\nint main()\n{\n    char text[] = \"world\";\n\n    String s0;\n    String s1(\"hello\");\n    String s2(std::move(s0));\n    String s3 = s1;\n    String s4(text);\n    s2 = s1;\n\n    if (s2 == s1)\n        std::cout << \"s2 == s1\" << std::endl;\n\n    foo(s1);\n    bar(s1);\n    foo(\"temporary\");\n    bar(\"temporary\");\n    String s5 = baz();\n\n    std::vector<String> svec;\n    //svec.push_back(s0);\n    svec.push_back(s1);\n    svec.push_back(s2);\n    svec.push_back(s3);\n    svec.push_back(s4);\n    svec.push_back(baz());\n    svec.push_back(\"good job\");\n\n    for (const auto &s : svec) {\n        std::cout << s << std::endl;\n    }\n\n    std::cout << \"Input a string: \";\n    String s6;\n    std::cin >> s6;\n    std::cout << s6 << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_18_StrBlob.cpp",
    "content": "#include \"ex14_18_StrBlob.h\"\n#include <algorithm>\n\n//==================================================================\n//\n//\t\tStrBlob - operators\n//\n//==================================================================\n\nbool operator==(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return *lhs.data == *rhs.data;\n}\n\nbool operator!=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());\n}\n\nbool operator> (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs < rhs);\n}\n\n//================================================================\n//\n//\t\tStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr < y.curr;\n}\n\nbool operator>(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr > y.curr;\n}\n\nbool operator<=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr <= y.curr;\n}\n\nbool operator>=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr >= y.curr;\n}\n\n//================================================================\n//\n//\t\tConstStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr < rhs.curr;\n}\n\nbool operator>(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr > rhs.curr;\n}\n\nbool operator<=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr <= rhs.curr;\n}\n\nbool operator>=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr >= rhs.curr;\n}\n\n//==================================================================\n//\n//\t\tcopy assignment operator and move assignment operator.\n//\n//==================================================================\n\nStrBlob& StrBlob::operator=(const StrBlob &lhs)\n{\n    data = make_shared<vector<string>>(*lhs.data);\n    return *this;\n}\n\nStrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        data = std::move(rhs.data);\n        rhs.data = nullptr;\n    }\n\n    return *this;\n}\n\n//==================================================================\n//\n//\t\tmembers\n//\n//==================================================================\n\nStrBlobPtr StrBlob::begin()\n{\n    return StrBlobPtr(*this);\n}\n\nStrBlobPtr StrBlob::end()\n{\n    return StrBlobPtr(*this, data->size());\n}\n\nConstStrBlobPtr StrBlob::cbegin() const\n{\n    return ConstStrBlobPtr(*this);\n}\n\nConstStrBlobPtr StrBlob::cend() const\n{\n    return ConstStrBlobPtr(*this, data->size());\n}\n"
  },
  {
    "path": "ch14/ex14_18_StrBlob.h",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nStrBlob, StrBlobPtr, ConstStrBlobPtr\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#ifndef CP5_STRBLOB_H_\n#define CP5_STRBLOB_H_\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <initializer_list>\nusing std::initializer_list;\n\n#include <memory>\nusing std::make_shared; using std::shared_ptr;\n\n#include <exception>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrBlobPtr;\nclass ConstStrBlobPtr;\n\n//=================================================================================\n//\n//\t\tStrBlob - custom vector<string>\n//\n//=================================================================================\n\nclass StrBlob {\n    using size_type = vector<string>::size_type;\n    friend class ConstStrBlobPtr;\n    friend class StrBlobPtr;\n    friend bool operator==(const StrBlob&, const StrBlob&);\n    friend bool operator!=(const StrBlob&, const StrBlob&);\n    friend bool operator< (const StrBlob&, const StrBlob&);\n    friend bool operator> (const StrBlob&, const StrBlob&);\n    friend bool operator<=(const StrBlob&, const StrBlob&);\n    friend bool operator>=(const StrBlob&, const StrBlob&);\n\npublic:\n    StrBlob() : data(make_shared<vector<string>>()) { }\n    StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) { }\n\n    StrBlob(const StrBlob &sb) : data(make_shared<vector<string>>(*sb.data)) { }\n    StrBlob& operator=(const StrBlob&);\n\n    StrBlob(StrBlob &&rhs) NOEXCEPT : data(std::move(rhs.data)) { }\n    StrBlob& operator=(StrBlob &&)NOEXCEPT;\n\n    StrBlobPtr begin();\n    StrBlobPtr end();\n\n    ConstStrBlobPtr cbegin() const;\n    ConstStrBlobPtr cend() const;\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void push_back(string &&s) { data->push_back(std::move(s)); }\n\n    void pop_back();\n    string& front();\n    string& back();\n    const string& front() const;\n    const string& back() const;\n\nprivate:\n    void check(size_type, const string&) const;\n\n    shared_ptr<vector<string>> data;\n};\n\nbool operator==(const StrBlob&, const StrBlob&);\nbool operator!=(const StrBlob&, const StrBlob&);\nbool operator< (const StrBlob&, const StrBlob&);\nbool operator> (const StrBlob&, const StrBlob&);\nbool operator<=(const StrBlob&, const StrBlob&);\nbool operator>=(const StrBlob&, const StrBlob&);\n\ninline void StrBlob::pop_back()\n{\n    check(0, \"pop_back on empty StrBlob\");\n    data->pop_back();\n}\n\ninline string& StrBlob::front()\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline string& StrBlob::back()\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline const string& StrBlob::front() const\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline const string& StrBlob::back() const\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline void StrBlob::check(size_type i, const string &msg) const\n{\n    if (i >= data->size()) throw std::out_of_range(msg);\n}\n\n//=================================================================================\n//\n//\t\tStrBlobPtr - custom iterator of StrBlob\n//\n//=================================================================================\n\nclass StrBlobPtr {\n    friend bool operator==(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator!=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator< (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator> (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator<=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\npublic:\n    StrBlobPtr() : curr(0) { }\n    StrBlobPtr(StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    string& deref() const;\n    StrBlobPtr& incr();\n\nprivate:\n    shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const StrBlobPtr&, const StrBlobPtr&);\nbool operator!=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator< (const StrBlobPtr&, const StrBlobPtr&);\nbool operator> (const StrBlobPtr&, const StrBlobPtr&);\nbool operator<=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\ninline string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline StrBlobPtr& StrBlobPtr::incr()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\n//=================================================================================\n//\n//\t\tConstStrBlobPtr - custom const_iterator of StrBlob\n//\n//=================================================================================\n\nclass ConstStrBlobPtr {\n    friend bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\npublic:\n    ConstStrBlobPtr() : curr(0) { }\n    ConstStrBlobPtr(const StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    const string& deref() const;\n    ConstStrBlobPtr& incr();\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\ninline const string& ConstStrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::incr()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\n#endif //CP5_STRBLOB_H_\n"
  },
  {
    "path": "ch14/ex14_18_StrBlobTest.cpp",
    "content": "#include \"ex14_18_StrBlob.h\"\n#include <iostream>\n\nint main()\n{\n    StrBlob sb1{ \"a\", \"b\", \"c\" };\n    StrBlob sb2{ \"a\", \"b\", \"b\" };\n\n    if (sb1 > sb2) {\n        for (ConstStrBlobPtr iter = sb1.cbegin(); iter < sb1.cend(); iter.incr())\n            std::cout << iter.deref() << \" \";\n        std::cout << std::endl;\n    }\n}\n"
  },
  {
    "path": "ch14/ex14_18_StrVec.cpp",
    "content": "#include \"ex14_18_StrVec.h\"\n#include <algorithm> // for_each, equal\n\nvoid StrVec::push_back(const std::string &s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n    auto data = alloc.allocate(e - b);\n    return{ data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n    if (elements) {\n        for_each(elements, first_free, [this](std::string &rhs){ alloc.destroy(&rhs); });\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nvoid StrVec::range_initialize(const std::string *first, const std::string *last)\n{\n    auto newdata = alloc_n_copy(first, last);\n    elements = newdata.first;\n    first_free = cap = newdata.second;\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n    range_initialize(rhs.begin(), rhs.end());\n}\n\nStrVec::StrVec(std::initializer_list<std::string> il)\n{\n    range_initialize(il.begin(), il.end());\n}\n\nStrVec::~StrVec()\n{\n    free();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n    auto data = alloc_n_copy(rhs.begin(), rhs.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n    auto newcapacity = size() ? 2 * size() : 1;\n    alloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n    resize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i)\n            alloc.construct(first_free++, s);\n    }\n    else if (count < size()) {\n        while (first_free != elements + count)\n            alloc.destroy(--first_free);\n    }\n}\n\nStrVec::StrVec(StrVec &&s) NOEXCEPT : elements(s.elements), first_free(s.first_free), cap(s.cap)\n{\n    // leave s in a state in which it is safe to run the destructor.\n    s.elements = s.first_free = s.cap = nullptr;\n}\n\nStrVec& StrVec::operator = (StrVec &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        free();\n        elements = rhs.elements;\n        first_free = rhs.first_free;\n        cap = rhs.cap;\n        rhs.elements = rhs.first_free = rhs.cap = nullptr;\n    }\n    return *this;\n}\n\nbool operator==(const StrVec &lhs, const StrVec &rhs)\n{\n    return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));\n}\n\nbool operator!=(const StrVec &lhs, const StrVec &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator<(const StrVec &lhs, const StrVec &rhs)\n{\n    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());\n}\n\nbool operator>(const StrVec &lhs, const StrVec &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const StrVec &lhs, const StrVec &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const StrVec &lhs, const StrVec &rhs)\n{\n    return !(lhs < rhs);\n}\n"
  },
  {
    "path": "ch14/ex14_18_StrVec.h",
    "content": "#ifndef CP5_STRVEC_H_\n#define CP5_STRVEC_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrVec\n{\n    friend bool operator==(const StrVec&, const StrVec&);\n    friend bool operator!=(const StrVec&, const StrVec&);\n    friend bool operator< (const StrVec&, const StrVec&);\n    friend bool operator> (const StrVec&, const StrVec&);\n    friend bool operator<=(const StrVec&, const StrVec&);\n    friend bool operator>=(const StrVec&, const StrVec&);\n\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(std::initializer_list<std::string>);\n    StrVec(const StrVec&);\n    StrVec& operator=(const StrVec&);\n    StrVec(StrVec&&) NOEXCEPT;\n    StrVec& operator=(StrVec&&)NOEXCEPT;\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    std::string& at(size_t pos) { return *(elements + pos); }\n    const std::string& at(size_t pos) const { return *(elements + pos); }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\nbool operator==(const StrVec&, const StrVec&);\nbool operator!=(const StrVec&, const StrVec&);\nbool operator< (const StrVec&, const StrVec&);\nbool operator> (const StrVec&, const StrVec&);\nbool operator<=(const StrVec&, const StrVec&);\nbool operator>=(const StrVec&, const StrVec&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_18_StrVecMain.cpp",
    "content": "#ifndef CP5_STRVEC_H_\n#define CP5_STRVEC_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrVec\n{\n    friend bool operator==(const StrVec&, const StrVec&);\n    friend bool operator!=(const StrVec&, const StrVec&);\n    friend bool operator< (const StrVec&, const StrVec&);\n    friend bool operator> (const StrVec&, const StrVec&);\n    friend bool operator<=(const StrVec&, const StrVec&);\n    friend bool operator>=(const StrVec&, const StrVec&);\n\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(std::initializer_list<std::string>);\n    StrVec(const StrVec&);\n    StrVec& operator=(const StrVec&);\n    StrVec(StrVec&&) NOEXCEPT;\n    StrVec& operator=(StrVec&&)NOEXCEPT;\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    std::string& at(size_t pos) { return *(elements + pos); }\n    const std::string& at(size_t pos) const { return *(elements + pos); }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\nbool operator==(const StrVec&, const StrVec&);\nbool operator!=(const StrVec&, const StrVec&);\nbool operator< (const StrVec&, const StrVec&);\nbool operator> (const StrVec&, const StrVec&);\nbool operator<=(const StrVec&, const StrVec&);\nbool operator>=(const StrVec&, const StrVec&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_18_String.cpp",
    "content": "#include \"ex14_18_String.h\"\n#include <algorithm>\n\n//===========================================================================\n//\n//\t\toperator - friend\n//\n//===========================================================================\n\nstd::ostream& operator<<(std::ostream &os, const String &lhs)\n{\n    os << lhs.c_str();\n    return os;\n}\n\nstd::istream& operator>>(std::istream &is, String &rhs)\n{\n    for (char c; (c = is.get()) != '\\n';) {\n        rhs.push_back(c);\n    }\n    return is;\n}\n\nbool operator==(const String &lhs, const String &rhs)\n{\n    return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));\n}\n\nbool operator!=(const String &lhs, const String &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator<(const String &lhs, const String &rhs)\n{\n    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());\n}\n\nbool operator>(const String &lhs, const String &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const String &lhs, const String &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const String &lhs, const String &rhs)\n{\n    return !(lhs < rhs);\n}\n\n//===========================================================================\n//\n//\t\tConstructors\n//\n//===========================================================================\n\nString::String(const char *s)\n{\n    char *sl = const_cast<char*>(s);\n    while (*sl)\n        ++sl;\n    range_initializer(s, ++sl);\n}\n\n//===========================================================================\n//\n//\t\tBig 5\n//\n//===========================================================================\n\nString::String(const String& rhs)\n{\n    range_initializer(rhs.elements, rhs.first_free);\n}\n\nString& String::operator = (const String &rhs)\n{\n    auto newstr = alloc_n_copy(rhs.elements, rhs.first_free);\n    free();\n    elements = newstr.first;\n    first_free = cap = newstr.second;\n    last_elem = first_free - 1;\n    return *this;\n}\n\nString::String(String &&s) NOEXCEPT : elements(s.elements), last_elem(s.last_elem), first_free(s.first_free), cap(s.cap)\n{\n    s.elements = s.last_elem = s.first_free = s.cap = nullptr;\n}\n\nString& String::operator = (String &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        free();\n        elements = rhs.elements;\n        last_elem = rhs.last_elem;\n        first_free = rhs.first_free;\n        cap = rhs.cap;\n        rhs.elements = rhs.last_elem = rhs.first_free = rhs.cap = nullptr;\n    }\n    return *this;\n}\n\nString::~String()\n{\n    free();\n}\n\n//===========================================================================\n//\n//\t\tmembers\n//\n//===========================================================================\n\nvoid String::push_back(const char c)\n{\n    chk_n_alloc();\n    *last_elem = c;\n    last_elem = first_free;\n    alloc.construct(first_free++, '\\0');\n}\n\nvoid String::reallocate()\n{\n    //\t\\0    |    -\n    //  ^          ^\n    // elements    first_free\n    // last_elem   cap\n\n    auto newcapacity = size() ? 2 * (size() + 1) : 2;\n    alloc_n_move(newcapacity);\n}\n\nvoid String::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size() + 1; ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    last_elem = dest - 1;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid String::free()\n{\n    if (elements) {\n        std::for_each(elements, first_free, [this](char &c){ alloc.destroy(&c); });\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nstd::pair<char*, char*>\nString::alloc_n_copy(const char *b, const char *e)\n{\n    auto str = alloc.allocate(e - b);\n    return{ str, std::uninitialized_copy(b, e, str) };\n}\n\nvoid String::range_initializer(const char *first, const char *last)\n{\n    auto newstr = alloc_n_copy(first, last);\n    elements = newstr.first;\n    first_free = cap = newstr.second;\n    last_elem = first_free - 1;\n}\n\nvoid String::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid String::resize(size_t count, char c)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i) {\n            *last_elem++ = c;\n            alloc.construct(first_free++, '\\0');\n        }\n\n    }\n    else if (count < size()) {\n        while (last_elem != elements + count) {\n            --last_elem;\n            alloc.destroy(--first_free);\n        }\n        *last_elem = '\\0';\n    }\n}\n\nvoid String::resize(size_t count)\n{\n    resize(count, ' ');\n}\n"
  },
  {
    "path": "ch14/ex14_18_String.h",
    "content": "#ifndef CP5_STRING_H__\n#define CP5_STRING_H__\n\n#include <memory>\n#include <iostream>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\n//===================================================================================\n//\n//\t\t|s|t|r|i|n|g|\\0|-------------------|\n//\t\t ^\t\t\t ^  ^ first_free       ^\n//\t\telements\t last_elem\t\t\t   cap\n//\n//===================================================================================\n\nclass String\n{\n    friend std::ostream& operator<<(std::ostream&, const String&);\n    friend std::istream& operator>>(std::istream&, String&);\n    friend bool operator==(const String&, const String&);\n    friend bool operator!=(const String&, const String&);\n    friend bool operator< (const String&, const String&);\n    friend bool operator> (const String&, const String&);\n    friend bool operator<=(const String&, const String&);\n    friend bool operator>=(const String&, const String&);\n\npublic:\n    String() : String(\"\") { }\n    String(const char *);\n    String(const String&);\n    String& operator=(const String&);\n    String(String &&) NOEXCEPT;\n    String& operator=(String&&)NOEXCEPT;\n    ~String();\n\n    void push_back(const char);\n\n    char* begin() const { return elements; }\n    char* end() const { return last_elem; }\n\n    const char *c_str() const { return elements; }\n    size_t size() const { return last_elem - elements; }\n    size_t length() const { return size(); }\n    size_t capacity() const { return cap - elements; }\n\n    void reserve(size_t);\n    void resize(size_t);\n    void resize(size_t, char);\n\nprivate:\n    std::pair<char*, char*> alloc_n_copy(const char*, const char*);\n    void range_initializer(const char*, const char*);\n    void free();\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void chk_n_alloc() { if (first_free == cap) reallocate(); }\n\nprivate:\n    char *elements;\n    char *last_elem;\n    char *first_free;\n    char *cap;\n    std::allocator<char> alloc;\n};\n\nstd::ostream& operator<<(std::ostream&, const String&);\nstd::istream& operator>>(std::istream&, String&);\nbool operator==(const String&, const String&);\nbool operator!=(const String&, const String&);\nbool operator< (const String&, const String&);\nbool operator> (const String&, const String&);\nbool operator<=(const String&, const String&);\nbool operator>=(const String&, const String&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_18_StringMain.cpp",
    "content": "#include \"ex14_18_String.h\"\n#include <vector>\n#include <iostream>\n#include <algorithm>\n#include <iterator>\n#include <string>\n\nvoid foo(String x)\n{\n    std::cout << x << std::endl;\n}\n\nvoid bar(const String& x)\n{\n    std::cout << x.c_str() << std::endl;\n}\n\nString baz()\n{\n    String ret(\"world\");\n    return ret;\n}\n\nint main()\n{\n    char text[] = \"world\";\n\n    String s0;\n    String s1(\"hello\");\n    String s2(std::move(s0));\n    String s3 = s1;\n    String s4(text);\n    s2 = s1;\n\n    if (s2 == s1)\n        std::cout << \"s2 == s1\" << std::endl;\n\n    foo(s1);\n    bar(s1);\n    foo(\"temporary\");\n    bar(\"temporary\");\n    String s5 = baz();\n\n    std::vector<String> svec;\n    //svec.push_back(s0);\n    svec.push_back(s1);\n    svec.push_back(s2);\n    svec.push_back(s3);\n    svec.push_back(s4);\n    svec.push_back(baz());\n    svec.push_back(\"good job\");\n\n    for (const auto &s : svec) {\n        std::cout << s << std::endl;\n    }\n\n    std::cout << \"Input a string: \";\n    String s6;\n    std::cin >> s6;\n    std::cout << s6 << std::endl;\n\n    if (s6 > s1)\n        std::cout << \"s6 > s1\" << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_22.cpp",
    "content": "#include \"ex14_22.h\"\n\nSales_data::Sales_data(std::istream &is) : Sales_data()\n{\n    is >> *this;\n}\n\nSales_data& Sales_data::operator+=(const Sales_data &rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\nstd::istream& operator>>(std::istream &is, Sales_data &item)\n{\n    double price = 0.0;\n    is >> item.bookNo >> item.units_sold >> price;\n    if (is)\n        item.revenue = price * item.units_sold;\n    else\n        item = Sales_data();\n    return is;\n}\n\nstd::ostream& operator<<(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue << \" \" << item.avg_price();\n    return os;\n}\n\nSales_data operator+(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum += rhs;\n    return sum;\n}\n\nSales_data& Sales_data::operator=(const std::string &isbn)\n{\n    *this = Sales_data(isbn);\n    return *this;\n}\n"
  },
  {
    "path": "ch14/ex14_22.h",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nSales_data\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#ifndef CP5_ex14_22_h\n#define CP5_ex14_22_h\n\n#include <string>\n#include <iostream>\n\nclass Sales_data {\n    friend std::istream& operator>>(std::istream&, Sales_data&);\n    friend std::ostream& operator<<(std::ostream&, const Sales_data&);\n    friend Sales_data operator+(const Sales_data&, const Sales_data&);\n\npublic:\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data() : Sales_data(\"\", 0, 0.0f){ }\n    Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f){ }\n    Sales_data(std::istream &is);\n\n    Sales_data& operator=(const std::string&);\n\n    Sales_data& operator+=(const Sales_data&);\n    std::string isbn() const { return bookNo; }\n\nprivate:\n    inline double avg_price() const;\n\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nstd::istream& operator>>(std::istream&, Sales_data&);\nstd::ostream& operator<<(std::ostream&, const Sales_data&);\nSales_data operator+(const Sales_data&, const Sales_data&);\n\ninline double Sales_data::avg_price() const\n{\n    return units_sold ? revenue/units_sold : 0;\n}\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_22_TEST.cpp",
    "content": "#include \"ex14_22.h\"\n\nint main()\n{\n    std::string strCp5(\"C++ Primer 5th\");\n    Sales_data cp5;\n    cp5 = strCp5;\n    std::cout << cp5 << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_23.cpp",
    "content": "#include \"ex14_23.h\"\n#include <algorithm> // for_each, equal\n\nvoid StrVec::push_back(const std::string &s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n    auto data = alloc.allocate(e - b);\n    return{ data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n    if (elements) {\n        for_each(elements, first_free, [this](std::string &rhs){ alloc.destroy(&rhs); });\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nvoid StrVec::range_initialize(const std::string *first, const std::string *last)\n{\n    auto newdata = alloc_n_copy(first, last);\n    elements = newdata.first;\n    first_free = cap = newdata.second;\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n    range_initialize(rhs.begin(), rhs.end());\n}\n\nStrVec::StrVec(std::initializer_list<std::string> il)\n{\n    range_initialize(il.begin(), il.end());\n}\n\nStrVec::~StrVec()\n{\n    free();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n    auto data = alloc_n_copy(rhs.begin(), rhs.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n    auto newcapacity = size() ? 2 * size() : 1;\n    alloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n    resize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i)\n            alloc.construct(first_free++, s);\n    }\n    else if (count < size()) {\n        while (first_free != elements + count)\n            alloc.destroy(--first_free);\n    }\n}\n\nStrVec::StrVec(StrVec &&s) NOEXCEPT : elements(s.elements), first_free(s.first_free), cap(s.cap)\n{\n    // leave s in a state in which it is safe to run the destructor.\n    s.elements = s.first_free = s.cap = nullptr;\n}\n\nStrVec& StrVec::operator = (StrVec &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        free();\n        elements = rhs.elements;\n        first_free = rhs.first_free;\n        cap = rhs.cap;\n        rhs.elements = rhs.first_free = rhs.cap = nullptr;\n    }\n    return *this;\n}\n\nbool operator==(const StrVec &lhs, const StrVec &rhs)\n{\n    return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));\n}\n\nbool operator!=(const StrVec &lhs, const StrVec &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator<(const StrVec &lhs, const StrVec &rhs)\n{\n    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());\n}\n\nbool operator>(const StrVec &lhs, const StrVec &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const StrVec &lhs, const StrVec &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const StrVec &lhs, const StrVec &rhs)\n{\n    return !(lhs < rhs);\n}\n\nStrVec& StrVec::operator=(std::initializer_list<std::string> il)\n{\n    auto data = alloc_n_copy(il.begin(), il.end());\n    free();\n    elements = data.first;\n    first_free = cap = data.second;\n    return *this;\n}\n"
  },
  {
    "path": "ch14/ex14_23.h",
    "content": "#ifndef CP5_STRVEC_H_\n#define CP5_STRVEC_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrVec\n{\n    friend bool operator==(const StrVec&, const StrVec&);\n    friend bool operator!=(const StrVec&, const StrVec&);\n    friend bool operator< (const StrVec&, const StrVec&);\n    friend bool operator> (const StrVec&, const StrVec&);\n    friend bool operator<=(const StrVec&, const StrVec&);\n    friend bool operator>=(const StrVec&, const StrVec&);\n\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(std::initializer_list<std::string>);\n    StrVec(const StrVec&);\n    StrVec& operator=(const StrVec&);\n    StrVec(StrVec&&) NOEXCEPT;\n    StrVec& operator=(StrVec&&)NOEXCEPT;\n    ~StrVec();\n\n    StrVec& operator=(std::initializer_list<std::string>);\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    std::string& at(size_t pos) { return *(elements + pos); }\n    const std::string& at(size_t pos) const { return *(elements + pos); }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\nbool operator==(const StrVec&, const StrVec&);\nbool operator!=(const StrVec&, const StrVec&);\nbool operator< (const StrVec&, const StrVec&);\nbool operator> (const StrVec&, const StrVec&);\nbool operator<=(const StrVec&, const StrVec&);\nbool operator>=(const StrVec&, const StrVec&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_23_TEST.cpp",
    "content": "#include \"ex14_23.h\"\n#include <iostream>\n#include <vector>\n\nint main()\n{\n    StrVec vec;\n    vec.reserve(6);\n    std::cout << \"capacity(reserve to 6): \" << vec.capacity() << std::endl;\n\n    vec.reserve(4);\n    std::cout << \"capacity(reserve to 4): \" << vec.capacity() << std::endl;\n\n    vec.push_back(\"hello\");\n    vec.push_back(\"world\");\n\n    vec.resize(4);\n\n    for (auto i = vec.begin(); i != vec.end(); ++i)\n        std::cout << *i << std::endl;\n    std::cout << \"-EOF-\" << std::endl;\n\n    vec.resize(1);\n\n    for (auto i = vec.begin(); i != vec.end(); ++i)\n        std::cout << *i << std::endl;\n    std::cout << \"-EOF-\" << std::endl;\n\n    StrVec vec_list{ \"hello\", \"world\", \"pezy\" };\n\n    for (auto i = vec_list.begin(); i != vec_list.end(); ++i)\n        std::cout << *i << \" \";\n    std::cout << std::endl;\n\n    // Test operator==\n\n    const StrVec const_vec_list = { \"hello\", \"world\", \"pezy\" };\n    if (vec_list == const_vec_list)\n        for (const auto &str : const_vec_list)\n            std::cout << str << \" \";\n    std::cout << std::endl;\n\n    // Test operator<\n    const StrVec const_vec_list_small = { \"hello\", \"pezy\", \"ok\" };\n    std::cout << (const_vec_list_small < const_vec_list) << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_24.cpp",
    "content": "#include \"ex14_24.h\"\n#include <algorithm>\n\n// constructor taking Size as days\n// the argument must be within (0, 2^32)\nDate::Date(Size days)\n{\n    // calculate the year\n    Size y400 =  days/YtoD_400;\n    Size y100 = (days - y400*YtoD_400)/YtoD_100;\n    Size y4   = (days - y400*YtoD_400 - y100*YtoD_100)/YtoD_4;\n    Size y    = (days - y400*YtoD_400 - y100*YtoD_100 - y4*YtoD_4)/365;\n    Size d    =  days - y400*YtoD_400 - y100*YtoD_100 - y4*YtoD_4 - y*365;\n    this->year = y400*400 + y100*100 + y4*4 + y;\n\n    // check if leap and choose the months vector accordingly\n    std::vector<Size>currYear\n            = isLeapYear(this->year) ? monthsVec_l : monthsVec_n;\n\n    // calculate day and month using find_if + lambda\n    Size D_accumu = 0, M_accumu = 0;\n    // @bug    fixed:  the variabbles above hade been declared inside the find_if as static\n    //                 which caused the bug. It works fine now after being move outside.\n\n    std::find_if(currYear.cbegin(), currYear.cend(), [&](Size m){\n\n        D_accumu += m;\n        M_accumu ++;\n\n        if(d < D_accumu)\n        {\n            this->month =   M_accumu;\n            this->day   =   d + m - D_accumu ;\n\n            return true;\n        }\n        else\n            return false;\n    });\n}\n\n// construcotr taking iostream\nDate::Date(std::istream &is, std::ostream &os)\n{\n    is >> day >> month >> year;\n\n    if(is)\n    {\n        if(check(*this)) return;\n        else\n        {\n            os << \"Invalid input! Object is default initialized.\";\n            *this = Date();\n        }\n    }\n    else\n    {\n        os << \"Invalid input! Object is default initialized.\";\n        *this = Date();\n    }\n\n}\n\n// copy constructor\nDate::Date(const Date &d) :\n    day(d.day), month(d.month), year(d.year)\n{ }\n\n// move constructor\nDate::Date(Date&& d) NOEXCEPT :\n    day(d.day), month(d.month), year(d.year)\n{ std::cout << \"copy moving\"; }\n\n// copy operator=\nDate &Date::operator= (const Date &d)\n{\n    this->day   = d.day;\n    this->month = d.month;\n    this->year  = d.year;\n\n    return *this;\n}\n\n// move operator=\nDate &Date::operator =(Date&& rhs) NOEXCEPT\n{\n    if(this != &rhs)\n    {\n        this->day   = rhs.day;\n        this->month = rhs.month;\n        this->year  = rhs.year;\n    }\n    std::cout << \"moving =\";\n\n    return *this;\n}\n\n// conver to days\nDate::Size Date::toDays() const\n{\n    Size result = this->day;\n\n    // check if leap and choose the months vector accordingly\n    std::vector<Size>currYear\n            = isLeapYear(this->year) ? monthsVec_l : monthsVec_n;\n\n    // calculate result + days by months\n    for(auto it = currYear.cbegin(); it != currYear.cbegin() + this->month -1; ++it)\n        result += *it;\n\n    // calculate result + days by years\n    result += (this->year/400)      * YtoD_400;\n    result += (this->year%400/100)  * YtoD_100;\n    result += (this->year%100/4)    * YtoD_4;\n    result += (this->year%4)        * YtoD_1;\n\n    return result;\n}\n\n// member operators:   +=  -=\n\nDate &Date::operator +=(Date::Size offset)\n{\n    *this = Date(this->toDays() + offset);\n    return *this;\n}\n\nDate &Date::operator -=(Date::Size offset)\n{\n    if(this->toDays() > offset)\n        *this = Date(this->toDays() - offset);\n    else\n        *this = Date();\n\n    return *this;\n}\n\n// non-member operators:  <<  >>  -   ==  !=  <   <=  >   >=\n\nstd::ostream&\noperator <<(std::ostream& os, const Date& d)\n{\n    os << d.day << \" \" << d.month << \" \" << d.year;\n    return os;\n}\n\nstd::istream&\noperator >>(std::istream& is, Date& d)\n{\n    if(is)\n    {\n        Date input = Date(is, std::cout);\n        if(check(input))    d = input;\n    }\n    return is;\n}\n\n\nint operator -(const Date &lhs, const Date &rhs)\n{\n    return lhs.toDays() - rhs.toDays();\n}\n\n\nbool operator ==(const Date &lhs, const Date &rhs)\n{\n    return (lhs.day   == rhs.day  ) &&\n           (lhs.month == rhs.month) &&\n           (lhs.year  == rhs.year )    ;\n}\n\n\nbool operator !=(const Date &lhs, const Date &rhs)\n{\n    return !(lhs == rhs);\n}\n\n\nbool operator < (const Date &lhs, const Date &rhs)\n{\n    return lhs.toDays() < rhs.toDays();\n}\n\n\nbool operator <=(const Date &lhs, const Date &rhs)\n{\n    return (lhs < rhs) || (lhs == rhs);\n}\n\n\nbool operator >(const Date &lhs, const Date &rhs)\n{\n    return !(lhs <= rhs);\n}\n\n\nbool operator >=(const Date &lhs, const Date &rhs)\n{\n    return !(lhs < rhs);\n}\n\n\nDate operator - (const Date &lhs, Date::Size rhs)\n{                                       //  ^^^ rhs must not be larger than 2^32-1\n    // copy lhs\n    Date result(lhs);\n    result -= rhs;\n\n    return result;\n}\n\n\nDate operator + (const Date &lhs, Date::Size rhs)\n{                                       //  ^^^ rhs must not be larger than 2^32-1\n    // copy lhs\n    Date result(lhs);\n    result += rhs;\n\n    return result;\n}\n"
  },
  {
    "path": "ch14/ex14_24.h",
    "content": "/***************************************************************************\n *  @file       date.h\n *  @author     Alan.W\n *  @date       15-17  JAN 2014\n *  @remark\n ***************************************************************************/\n//\n// Exercise 7.40:\n// Choose one of the following abstractions (or an abstraction of your own choosing).\n// Determine what data are needed in the class. Provide an appropriate set of constructors.\n// Explain your decisions.\n//\n// Exercise 14.5:\n// In exercise 7.40 from § 7.5.1 (p. 291) you wrote a sketch of one of the\n// following classes. Decide what, if any, overloaded operators your class\n// should provide.\n//      -   =   <   >   <=  >=  ++  --  <<  >>  ==  !=  +=  -=\n// Exercise 14.8:\n// Define an output operator for the class you chose in exercise 7.40 from\n// § 7.5.1 (p. 291).\n//\n// Exercise 14.12:\n// Define an input operator for the class you used in exercise 7.40 from\n// § 7.5.1 (p. 291). Be sure the operator handles input errors.\n//\n// Exercise 14.15:\n// Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291)\n// define any of the arithmetic operators? If so, implement them.\n// If not, explain why not.\n//\n//      arithmetic operators :  all non-members\n//      +   :   Date + Size\n//      -   :   Date - Size\n//      -   :   Date - Date\n//\n// Exercise 14.17:\n// Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291) define\n// the equality operators? If so, implement them. If not, explain why not.\n//\n// Exercise 14.19:\n// Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291) define\n// the relational operators? If so, implement them. If not, explain why not.\n//\n// Exercise 14.25:\n// Implement any other assignment operators your class should define.\n// Explain which types should be used as operands and why.\n//\n\n#ifndef DATE_H\n#define DATE_H\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\n#include <iostream>\n#include <vector>\n\nclass Date\n{\n    friend  bool            operator ==(const Date& lhs, const Date& rhs);\n    friend  bool            operator < (const Date &lhs, const Date &rhs);\n    friend  bool            check(const Date &d);\n    friend  std::ostream&   operator <<(std::ostream& os, const Date& d);\npublic:\n    typedef std::size_t Size;\n\n    // default constructor\n    Date() = default;\n    // constructor taking Size as days\n    explicit Date(Size days);\n    // constructor taking three Size\n    Date(Size d, Size m, Size y) : day(d), month(m), year(y) { }\n    // constructor taking iostream\n    Date(std::istream &is, std::ostream &os);\n\n    // copy constructor\n    Date(const Date& d);\n    // move constructor\n    Date(Date&& d) NOEXCEPT;\n\n    // copy operator=\n    Date& operator= (const Date& d);\n    // move operator=\n    Date& operator= (Date&& rhs) NOEXCEPT;\n\n    // destructor  --  in this case, user-defined destructor is not nessary.\n    ~Date(){ std::cout << \"destroying\\n\"; }\n\n    // members\n    Size toDays() const;  //not implemented yet.\n    Date& operator +=(Size offset);\n    Date& operator -=(Size offset);\n\n\nprivate:\n    Size    day = 1;\n    Size    month = 1;\n    Size    year = 0;\n};\n\nstatic const Date::Size YtoD_400 = 146097;    //365*400 + 400/4 -3 == 146097\nstatic const Date::Size YtoD_100 =  36524;    //365*100 + 100/4 -1 ==  36524\nstatic const Date::Size YtoD_4   =   1461;    //365*4 + 1          ==   1461\nstatic const Date::Size YtoD_1   =    365;    //365\n\n// normal year\nstatic const std::vector<Date::Size> monthsVec_n =\n{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n\n// leap year\nstatic const std::vector<Date::Size> monthsVec_l =\n{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n\n// non-member operators:  <<  >>  -   ==  !=  <   <=  >   >=\n//\nstd::ostream&\noperator <<(std::ostream& os, const Date& d);\nstd::istream&\noperator >>(std::istream& is, Date& d);\nint\noperator - (const Date& lhs, const Date& rhs);\nbool\noperator ==(const Date& lhs, const Date& rhs);\nbool\noperator !=(const Date& lhs, const Date& rhs);\nbool\noperator < (const Date& lhs, const Date& rhs);\nbool\noperator <=(const Date& lhs, const Date& rhs);\nbool\noperator  >(const Date& lhs, const Date& rhs);\nbool\noperator >=(const Date& lhs, const Date& rhs);\nDate\noperator - (const Date& lhs, Date::Size  rhs);\nDate\noperator  +(const Date& lhs, Date::Size  rhs);\n\n\n\n//  utillities:\nbool check(const Date &d);\ninline bool\nisLeapYear(Date::Size y);\n\n\n\n\n// check if the date object passed in is valid\n inline bool\n check(const Date &d)\n {\n     if(d.month==0 || d.month >12)\n         return false;\n     else\n     {\n         //    month == 1 3 5 7 8 10 12\n         if(d.month==1 || d.month==3 || d.month==5 || d.month==7 ||\n            d.month==8 || d.month==10|| d.month==12)\n         {\n             if(d.day==0 || d.day > 31) return false;\n             else\n                return true;\n         }\n         else\n         {\n             //    month == 4 6 9 11\n             if(d.month==4 || d.month==6 || d.month==9 || d.month==11)\n             {\n                 if(d.day==0 || d.day > 30) return false;\n                 else\n                     return true;\n             }\n             else\n             {\n                 //    month == 2\n                 if(isLeapYear(d.year))\n                 {\n                     if(d.day==0 || d.day >29)  return false;\n                     else\n                         return true;\n                 }\n                 else\n                 {\n                     if(d.day==0 || d.day >28)  return false;\n                     else\n                         return true;\n                 }\n             }\n         }\n     }\n }\n\n inline bool\n isLeapYear(Date::Size y)\n {\n     if (!(y%400))\n     {\n         return true;\n     }\n     else\n     {\n         if(!(y%100))\n         {\n             return false;\n         }\n         else\n             return !(y%4);\n     }\n }\n#endif // DATE_H\n"
  },
  {
    "path": "ch14/ex14_24_TEST.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       14  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 14.20:\n// Define the addition and compound-assignment operators for your Sales_data class.\n//\n// Exercise 14.22:\n// Define a version of the assignment operator that can assign a string representing\n// an ISBN to a Sales_data.\n//\n// Exercise 14.23:\n// Define an initializer_list assignment operator for your version of the StrVec\n// class.\n//\n// Exercise 14.24:\n// Decide whether the class you used in exercise 7.40 from § 7.5.1 (p. 291) needs a\n// copy- and move-assignment operator. If so, define those operators.\n//\n\n#include \"ex14_24.h\"\n#include <iostream>\n\nint main()\n{\n\n    Date lhs(9999999), rhs(1);\n\n    std::cout << (lhs -= 12000) <<\"\\n\";\n\n\n    return 0;\n}\n"
  },
  {
    "path": "ch14/ex14_26_StrBlob.cpp",
    "content": "#include \"ex14_26_StrBlob.h\"\n#include <algorithm>\n\n//==================================================================\n//\n//\t\tStrBlob - operators\n//\n//==================================================================\n\nbool operator==(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return *lhs.data == *rhs.data;\n}\n\nbool operator!=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());\n}\n\nbool operator> (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs < rhs);\n}\n\n//================================================================\n//\n//\t\tStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr < y.curr;\n}\n\nbool operator>(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr > y.curr;\n}\n\nbool operator<=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr <= y.curr;\n}\n\nbool operator>=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr >= y.curr;\n}\n\n//================================================================\n//\n//\t\tConstStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr < rhs.curr;\n}\n\nbool operator>(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr > rhs.curr;\n}\n\nbool operator<=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr <= rhs.curr;\n}\n\nbool operator>=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr >= rhs.curr;\n}\n\n//==================================================================\n//\n//\t\tcopy assignment operator and move assignment operator.\n//\n//==================================================================\n\nStrBlob& StrBlob::operator=(const StrBlob &lhs)\n{\n    data = make_shared<vector<string>>(*lhs.data);\n    return *this;\n}\n\nStrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        data = std::move(rhs.data);\n        rhs.data = nullptr;\n    }\n\n    return *this;\n}\n\n//==================================================================\n//\n//\t\tmembers\n//\n//==================================================================\n\nStrBlobPtr StrBlob::begin()\n{\n    return StrBlobPtr(*this);\n}\n\nStrBlobPtr StrBlob::end()\n{\n    return StrBlobPtr(*this, data->size());\n}\n\nConstStrBlobPtr StrBlob::cbegin() const\n{\n    return ConstStrBlobPtr(*this);\n}\n\nConstStrBlobPtr StrBlob::cend() const\n{\n    return ConstStrBlobPtr(*this, data->size());\n}\n"
  },
  {
    "path": "ch14/ex14_26_StrBlob.h",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nStrBlob, StrBlobPtr, ConstStrBlobPtr\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#ifndef CP5_STRBLOB_H_\n#define CP5_STRBLOB_H_\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <initializer_list>\nusing std::initializer_list;\n\n#include <memory>\nusing std::make_shared; using std::shared_ptr;\n\n#include <exception>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrBlobPtr;\nclass ConstStrBlobPtr;\n\n//=================================================================================\n//\n//\t\tStrBlob - custom vector<string>\n//\n//=================================================================================\n\nclass StrBlob {\n    using size_type = vector<string>::size_type;\n    friend class ConstStrBlobPtr;\n    friend class StrBlobPtr;\n    friend bool operator==(const StrBlob&, const StrBlob&);\n    friend bool operator!=(const StrBlob&, const StrBlob&);\n    friend bool operator< (const StrBlob&, const StrBlob&);\n    friend bool operator> (const StrBlob&, const StrBlob&);\n    friend bool operator<=(const StrBlob&, const StrBlob&);\n    friend bool operator>=(const StrBlob&, const StrBlob&);\n\npublic:\n    StrBlob() : data(make_shared<vector<string>>()) { }\n    StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) { }\n\n    StrBlob(const StrBlob &sb) : data(make_shared<vector<string>>(*sb.data)) { }\n    StrBlob& operator=(const StrBlob&);\n\n    StrBlob(StrBlob &&rhs) NOEXCEPT : data(std::move(rhs.data)) { }\n    StrBlob& operator=(StrBlob &&)NOEXCEPT;\n\n    StrBlobPtr begin();\n    StrBlobPtr end();\n\n    ConstStrBlobPtr cbegin() const;\n    ConstStrBlobPtr cend() const;\n\n    string& operator[](size_t n);\n    const string& operator[](size_t n) const;\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void push_back(string &&s) { data->push_back(std::move(s)); }\n\n    void pop_back();\n    string& front();\n    string& back();\n    const string& front() const;\n    const string& back() const;\n\nprivate:\n    void check(size_type, const string&) const;\n\n    shared_ptr<vector<string>> data;\n};\n\nbool operator==(const StrBlob&, const StrBlob&);\nbool operator!=(const StrBlob&, const StrBlob&);\nbool operator< (const StrBlob&, const StrBlob&);\nbool operator> (const StrBlob&, const StrBlob&);\nbool operator<=(const StrBlob&, const StrBlob&);\nbool operator>=(const StrBlob&, const StrBlob&);\n\ninline void StrBlob::pop_back()\n{\n    check(0, \"pop_back on empty StrBlob\");\n    data->pop_back();\n}\n\ninline string& StrBlob::front()\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline string& StrBlob::back()\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline const string& StrBlob::front() const\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline const string& StrBlob::back() const\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline void StrBlob::check(size_type i, const string &msg) const\n{\n    if (i >= data->size()) throw std::out_of_range(msg);\n}\n\ninline string& StrBlob::operator[](size_t n)\n{\n    check(n, \"out of range\");\n    return data->at(n);\n}\n\ninline const string& StrBlob::operator[](size_t n) const\n{\n    check(n, \"out of range\");\n    return data->at(n);\n}\n\n//=================================================================================\n//\n//\t\tStrBlobPtr - custom iterator of StrBlob\n//\n//=================================================================================\n\nclass StrBlobPtr {\n    friend bool operator==(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator!=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator< (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator> (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator<=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\npublic:\n    StrBlobPtr() : curr(0) { }\n    StrBlobPtr(StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    string& deref() const;\n    StrBlobPtr& incr();\n\n    string& operator[](size_t n);\n    const string& operator[](size_t n) const;\n\nprivate:\n    shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const StrBlobPtr&, const StrBlobPtr&);\nbool operator!=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator< (const StrBlobPtr&, const StrBlobPtr&);\nbool operator> (const StrBlobPtr&, const StrBlobPtr&);\nbool operator<=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\ninline string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline StrBlobPtr& StrBlobPtr::incr()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\ninline string& StrBlobPtr::operator[](size_t n)\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\ninline const string& StrBlobPtr::operator[](size_t n) const\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\n//=================================================================================\n//\n//\t\tConstStrBlobPtr - custom const_iterator of StrBlob\n//\n//=================================================================================\n\nclass ConstStrBlobPtr {\n    friend bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\npublic:\n    ConstStrBlobPtr() : curr(0) { }\n    ConstStrBlobPtr(const StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    const string& deref() const;\n    ConstStrBlobPtr& incr();\n\n    const string& operator[](size_t n) const;\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\ninline const string& ConstStrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::incr()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\ninline const string& ConstStrBlobPtr::operator[](size_t n) const\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\n#endif //CP5_STRBLOB_H_\n"
  },
  {
    "path": "ch14/ex14_26_StrBlobTest.cpp",
    "content": "#include \"ex14_26_StrBlob.h\"\n#include <iostream>\n\nint main()\n{\n    StrBlob sb1{ \"a\", \"b\", \"c\" };\n    StrBlob sb2 = sb1;\n\n    sb2[2] = \"b\";\n\n    if (sb1 > sb2) {\n        for (ConstStrBlobPtr iter = sb1.cbegin(); iter < sb1.cend(); iter.incr())\n            std::cout << iter.deref() << \" \";\n        std::cout << std::endl;\n    }\n\n    StrBlobPtr iter(sb2);\n    std::cout << iter[2] << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_26_StrVec.cpp",
    "content": "#include \"ex14_26_StrVec.h\"\n#include <algorithm> // for_each, equal\n\nvoid StrVec::push_back(const std::string &s)\n{\n\tchk_n_alloc();\n\talloc.construct(first_free++, s);\n}\n\nstd::pair<std::string*, std::string*>\nStrVec::alloc_n_copy(const std::string *b, const std::string *e)\n{\n\tauto data = alloc.allocate(e-b);\n\treturn { data, std::uninitialized_copy(b, e, data) };\n}\n\nvoid StrVec::free()\n{\n\tif (elements) {\n\t\tfor_each(elements, first_free, [this](std::string &rhs){ alloc.destroy(&rhs); });\n\t\talloc.deallocate(elements, cap - elements);\n\t}\n}\n\nvoid StrVec::range_initialize(const std::string *first, const std::string *last)\n{\n\tauto newdata = alloc_n_copy(first, last);\n\telements = newdata.first;\n\tfirst_free = cap = newdata.second;\n}\n\nStrVec::StrVec(const StrVec &rhs)\n{\n\trange_initialize(rhs.begin(), rhs.end());\n}\n\nStrVec::StrVec(std::initializer_list<std::string> il)\n{\n\trange_initialize(il.begin(), il.end());\n}\n\nStrVec::~StrVec()\n{\n\tfree();\n}\n\nStrVec& StrVec::operator = (const StrVec &rhs)\n{\n\tauto data = alloc_n_copy(rhs.begin(), rhs.end());\n\tfree();\n\telements = data.first;\n\tfirst_free = cap = data.second;\n\treturn *this;\n}\n\nvoid StrVec::alloc_n_move(size_t new_cap)\n{\n\tauto newdata = alloc.allocate(new_cap);\n\tauto dest = newdata;\n\tauto elem = elements;\n\tfor (size_t i = 0; i != size(); ++i)\n\t\talloc.construct(dest++, std::move(*elem++));\n\tfree();\n\telements = newdata;\n\tfirst_free = dest;\n\tcap = elements + new_cap;\n}\n\nvoid StrVec::reallocate()\n{\n\tauto newcapacity = size() ? 2 * size() : 1;\n\talloc_n_move(newcapacity);\n}\n\nvoid StrVec::reserve(size_t new_cap)\n{\n\tif (new_cap <= capacity()) return;\n\talloc_n_move(new_cap);\n}\n\nvoid StrVec::resize(size_t count)\n{\n\tresize(count, std::string());\n}\n\nvoid StrVec::resize(size_t count, const std::string &s)\n{\n\tif (count > size()) {\n\t\tif (count > capacity()) reserve(count * 2);\n\t\tfor (size_t i = size(); i != count; ++i)\n\t\t\talloc.construct(first_free++, s);\n\t}\n\telse if (count < size()) {\n\t\twhile (first_free != elements + count)\n\t\t\talloc.destroy(--first_free);\n\t}\n}\n\nStrVec::StrVec(StrVec &&s) NOEXCEPT : elements(s.elements), first_free(s.first_free), cap(s.cap)\n{\n\t// leave s in a state in which it is safe to run the destructor.\n\ts.elements = s.first_free = s.cap = nullptr;\n}\n\nStrVec& StrVec::operator = (StrVec &&rhs) NOEXCEPT\n{\n\tif (this != &rhs) {\n\t\tfree();\n\t\telements = rhs.elements;\n\t\tfirst_free = rhs.first_free;\n\t\tcap = rhs.cap;\n\t\trhs.elements = rhs.first_free = rhs.cap = nullptr;\n\t}\n\treturn *this;\n}\n\nbool operator==(const StrVec &lhs, const StrVec &rhs)\n{\n\treturn (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));\n}\n\nbool operator!=(const StrVec &lhs, const StrVec &rhs)\n{\n\treturn !(lhs == rhs);\n}\n\nbool operator<(const StrVec &lhs, const StrVec &rhs)\n{\n\treturn std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());\n}\n\nbool operator>(const StrVec &lhs, const StrVec &rhs)\n{\n\treturn rhs < lhs;\n}\n\nbool operator<=(const StrVec &lhs, const StrVec &rhs)\n{\n\treturn !(rhs < lhs);\n}\n\nbool operator>=(const StrVec &lhs, const StrVec &rhs)\n{\n\treturn !(lhs < rhs);\n}\n"
  },
  {
    "path": "ch14/ex14_26_StrVec.h",
    "content": "#ifndef CP5_STRVEC_H_\n#define CP5_STRVEC_H_\n\n#include <memory>\n#include <string>\n#include <initializer_list>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrVec\n{\n    friend bool operator==(const StrVec&, const StrVec&);\n    friend bool operator!=(const StrVec&, const StrVec&);\n    friend bool operator< (const StrVec&, const StrVec&);\n    friend bool operator> (const StrVec&, const StrVec&);\n    friend bool operator<=(const StrVec&, const StrVec&);\n    friend bool operator>=(const StrVec&, const StrVec&);\n\npublic:\n    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }\n    StrVec(std::initializer_list<std::string>);\n    StrVec(const StrVec&);\n    StrVec& operator=(const StrVec&);\n    StrVec(StrVec&&) NOEXCEPT;\n    StrVec& operator=(StrVec&&)NOEXCEPT;\n    ~StrVec();\n\n    void push_back(const std::string&);\n    size_t size() const { return first_free - elements; }\n    size_t capacity() const { return cap - elements; }\n    std::string *begin() const { return elements; }\n    std::string *end() const { return first_free; }\n\n    std::string& at(size_t pos) { return *(elements + pos); }\n    const std::string& at(size_t pos) const { return *(elements + pos); }\n\n    std::string& operator[](size_t n) { return elements[n]; }\n    const std::string& operator[](size_t n) const { return elements[n]; }\n\n    void reserve(size_t new_cap);\n    void resize(size_t count);\n    void resize(size_t count, const std::string&);\n\nprivate:\n    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);\n    void free();\n    void chk_n_alloc() { if (size() == capacity()) reallocate(); }\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void range_initialize(const std::string*, const std::string*);\n\nprivate:\n    std::string *elements;\n    std::string *first_free;\n    std::string *cap;\n    std::allocator<std::string> alloc;\n};\n\nbool operator==(const StrVec&, const StrVec&);\nbool operator!=(const StrVec&, const StrVec&);\nbool operator< (const StrVec&, const StrVec&);\nbool operator> (const StrVec&, const StrVec&);\nbool operator<=(const StrVec&, const StrVec&);\nbool operator>=(const StrVec&, const StrVec&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_26_StrVecMain.cpp",
    "content": "#include \"ex14_26_StrVec.h\"\n#include <iostream>\n#include <vector>\n\nint main()\n{\n    StrVec vec;\n    vec.reserve(6);\n    std::cout << \"capacity(reserve to 6): \" << vec.capacity() << std::endl;\n\n    vec.reserve(4);\n    std::cout << \"capacity(reserve to 4): \" << vec.capacity() << std::endl;\n\n    vec.push_back(\"hello\");\n    vec.push_back(\"world\");\n\n    vec.resize(4);\n\n    for (auto i = vec.begin(); i != vec.end(); ++i)\n        std::cout << *i << std::endl;\n    std::cout << \"-EOF-\" << std::endl;\n\n    vec.resize(1);\n\n    for (auto i = vec.begin(); i != vec.end(); ++i)\n        std::cout << *i << std::endl;\n    std::cout << \"-EOF-\" << std::endl;\n\n    StrVec vec_list{ \"hello\", \"world\", \"pezy\" };\n\n    for (auto i = vec_list.begin(); i != vec_list.end(); ++i)\n        std::cout << *i << \" \";\n    std::cout << std::endl;\n\n    // Test operator==\n\n    const StrVec const_vec_list{ \"hello\", \"world\", \"pezy\" };\n    if (vec_list == const_vec_list)\n        for (const auto &str : const_vec_list)\n            std::cout << str << \" \";\n    std::cout << std::endl;\n\n    // Test operator<\n    const StrVec const_vec_list_small{ \"hello\", \"pezy\", \"ok\" };\n    std::cout << (const_vec_list_small < const_vec_list) << std::endl;\n\n    // Test []\n    std::cout << const_vec_list_small[1] << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_26_String.cpp",
    "content": "#include \"ex14_26_String.h\"\n#include <algorithm>\n\n//===========================================================================\n//\n//\t\toperator - friend\n//\n//===========================================================================\n\nstd::ostream& operator<<(std::ostream &os, const String &lhs)\n{\n    os << lhs.c_str();\n    return os;\n}\n\nstd::istream& operator>>(std::istream &is, String &rhs)\n{\n    for (char c; (c = is.get()) != '\\n';) {\n        rhs.push_back(c);\n    }\n    return is;\n}\n\nbool operator==(const String &lhs, const String &rhs)\n{\n    return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));\n}\n\nbool operator!=(const String &lhs, const String &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator<(const String &lhs, const String &rhs)\n{\n    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());\n}\n\nbool operator>(const String &lhs, const String &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const String &lhs, const String &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const String &lhs, const String &rhs)\n{\n    return !(lhs < rhs);\n}\n\n//===========================================================================\n//\n//\t\tConstructors\n//\n//===========================================================================\n\nString::String(const char *s)\n{\n    char *sl = const_cast<char*>(s);\n    while (*sl)\n        ++sl;\n    range_initializer(s, ++sl);\n}\n\n//===========================================================================\n//\n//\t\tBig 5\n//\n//===========================================================================\n\nString::String(const String& rhs)\n{\n    range_initializer(rhs.elements, rhs.first_free);\n}\n\nString& String::operator = (const String &rhs)\n{\n    auto newstr = alloc_n_copy(rhs.elements, rhs.first_free);\n    free();\n    elements = newstr.first;\n    first_free = cap = newstr.second;\n    last_elem = first_free - 1;\n    return *this;\n}\n\nString::String(String &&s) NOEXCEPT : elements(s.elements), last_elem(s.last_elem), first_free(s.first_free), cap(s.cap)\n{\n    s.elements = s.last_elem = s.first_free = s.cap = nullptr;\n}\n\nString& String::operator = (String &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        free();\n        elements = rhs.elements;\n        last_elem = rhs.last_elem;\n        first_free = rhs.first_free;\n        cap = rhs.cap;\n        rhs.elements = rhs.last_elem = rhs.first_free = rhs.cap = nullptr;\n    }\n    return *this;\n}\n\nString::~String()\n{\n    free();\n}\n\n//===========================================================================\n//\n//\t\tmembers\n//\n//===========================================================================\n\nvoid String::push_back(const char c)\n{\n    chk_n_alloc();\n    *last_elem = c;\n    last_elem = first_free;\n    alloc.construct(first_free++, '\\0');\n}\n\nvoid String::reallocate()\n{\n    //\t\\0    |    -\n    //  ^          ^\n    // elements    first_free\n    // last_elem   cap\n\n    auto newcapacity = size() ? 2 * (size() + 1) : 2;\n    alloc_n_move(newcapacity);\n}\n\nvoid String::alloc_n_move(size_t new_cap)\n{\n    auto newdata = alloc.allocate(new_cap);\n    auto dest = newdata;\n    auto elem = elements;\n    for (size_t i = 0; i != size() + 1; ++i)\n        alloc.construct(dest++, std::move(*elem++));\n    free();\n    elements = newdata;\n    last_elem = dest - 1;\n    first_free = dest;\n    cap = elements + new_cap;\n}\n\nvoid String::free()\n{\n    if (elements) {\n        std::for_each(elements, first_free, [this](char &c){ alloc.destroy(&c); });\n        alloc.deallocate(elements, cap - elements);\n    }\n}\n\nstd::pair<char*, char*>\nString::alloc_n_copy(const char *b, const char *e)\n{\n    auto str = alloc.allocate(e - b);\n    return{ str, std::uninitialized_copy(b, e, str) };\n}\n\nvoid String::range_initializer(const char *first, const char *last)\n{\n    auto newstr = alloc_n_copy(first, last);\n    elements = newstr.first;\n    first_free = cap = newstr.second;\n    last_elem = first_free - 1;\n}\n\nvoid String::reserve(size_t new_cap)\n{\n    if (new_cap <= capacity()) return;\n    alloc_n_move(new_cap);\n}\n\nvoid String::resize(size_t count, char c)\n{\n    if (count > size()) {\n        if (count > capacity()) reserve(count * 2);\n        for (size_t i = size(); i != count; ++i) {\n            *last_elem++ = c;\n            alloc.construct(first_free++, '\\0');\n        }\n\n    }\n    else if (count < size()) {\n        while (last_elem != elements + count) {\n            --last_elem;\n            alloc.destroy(--first_free);\n        }\n        *last_elem = '\\0';\n    }\n}\n\nvoid String::resize(size_t count)\n{\n    resize(count, ' ');\n}\n"
  },
  {
    "path": "ch14/ex14_26_String.h",
    "content": "#ifndef CP5_STRING_H__\n#define CP5_STRING_H__\n\n#include <memory>\n#include <iostream>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\n//===================================================================================\n//\n//\t\t|s|t|r|i|n|g|\\0|-------------------|\n//\t\t ^\t\t\t ^  ^ first_free       ^\n//\t\telements\t last_elem\t\t\t   cap\n//\n//===================================================================================\n\nclass String\n{\n    friend std::ostream& operator<<(std::ostream&, const String&);\n    friend std::istream& operator>>(std::istream&, String&);\n    friend bool operator==(const String&, const String&);\n    friend bool operator!=(const String&, const String&);\n    friend bool operator< (const String&, const String&);\n    friend bool operator> (const String&, const String&);\n    friend bool operator<=(const String&, const String&);\n    friend bool operator>=(const String&, const String&);\n\npublic:\n    String() : String(\"\") { }\n    String(const char *);\n    String(const String&);\n    String& operator=(const String&);\n    String(String &&) NOEXCEPT;\n    String& operator=(String&&)NOEXCEPT;\n    ~String();\n\n    void push_back(const char);\n\n    char* begin() const { return elements; }\n    char* end() const { return last_elem; }\n\n    char& operator[](size_t n) { return elements[n]; }\n    const char& operator[](size_t n) const { return elements[n]; }\n\n    const char *c_str() const { return elements; }\n    size_t size() const { return last_elem - elements; }\n    size_t length() const { return size(); }\n    size_t capacity() const { return cap - elements; }\n\n    void reserve(size_t);\n    void resize(size_t);\n    void resize(size_t, char);\n\nprivate:\n    std::pair<char*, char*> alloc_n_copy(const char*, const char*);\n    void range_initializer(const char*, const char*);\n    void free();\n    void reallocate();\n    void alloc_n_move(size_t new_cap);\n    void chk_n_alloc() { if (first_free == cap) reallocate(); }\n\nprivate:\n    char *elements;\n    char *last_elem;\n    char *first_free;\n    char *cap;\n    std::allocator<char> alloc;\n};\n\nstd::ostream& operator<<(std::ostream&, const String&);\nstd::istream& operator>>(std::istream&, String&);\nbool operator==(const String&, const String&);\nbool operator!=(const String&, const String&);\nbool operator< (const String&, const String&);\nbool operator> (const String&, const String&);\nbool operator<=(const String&, const String&);\nbool operator>=(const String&, const String&);\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_26_StringMain.cpp",
    "content": "#include \"ex14_26_String.h\"\n#include <vector>\n#include <iostream>\n#include <algorithm>\n#include <iterator>\n#include <string>\n\nvoid foo(String x)\n{\n    std::cout << x << std::endl;\n}\n\nvoid bar(const String& x)\n{\n    std::cout << x.c_str() << std::endl;\n}\n\nString baz()\n{\n    String ret(\"world\");\n    return ret;\n}\n\nint main()\n{\n    char text[] = \"world\";\n\n    String s0;\n    String s1(\"hello\");\n    String s2(std::move(s0));\n    String s3 = s1;\n    String s4(text);\n    s2 = s1;\n\n    if (s2 == s1)\n        std::cout << \"s2 == s1\" << std::endl;\n\n    foo(s1);\n    bar(s1);\n    foo(\"temporary\");\n    bar(\"temporary\");\n    String s5 = baz();\n\n    std::vector<String> svec;\n    //svec.push_back(s0);\n    svec.push_back(s1);\n    svec.push_back(s2);\n    svec.push_back(s3);\n    svec.push_back(s4);\n    svec.push_back(baz());\n    svec.push_back(\"good job\");\n\n    for (const auto &s : svec) {\n        std::cout << s << std::endl;\n    }\n\n    std::cout << \"Input a string: \";\n    String s6;\n    std::cin >> s6;\n    std::cout << s6 << std::endl;\n\n    if (s6 > s1)\n        std::cout << \"s6 > s1\" << std::endl;\n\n    std::cout << s5[2] << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_27_28_StrBlob.cpp",
    "content": "#include \"ex14_27_28_StrBlob.h\"\n#include <algorithm>\n\n//==================================================================\n//\n//\t\tStrBlob - operators\n//\n//==================================================================\n\nbool operator==(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return *lhs.data == *rhs.data;\n}\n\nbool operator!=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());\n}\n\nbool operator> (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs < rhs);\n}\n\n//================================================================\n//\n//\t\tStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr < y.curr;\n}\n\nbool operator>(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr > y.curr;\n}\n\nbool operator<=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr <= y.curr;\n}\n\nbool operator>=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr >= y.curr;\n}\n\n//================================================================\n//\n//\t\tConstStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr < rhs.curr;\n}\n\nbool operator>(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr > rhs.curr;\n}\n\nbool operator<=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr <= rhs.curr;\n}\n\nbool operator>=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr >= rhs.curr;\n}\n\n//==================================================================\n//\n//\t\tcopy assignment operator and move assignment operator.\n//\n//==================================================================\n\nStrBlob& StrBlob::operator=(const StrBlob &lhs)\n{\n    data = make_shared<vector<string>>(*lhs.data);\n    return *this;\n}\n\nStrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        data = std::move(rhs.data);\n        rhs.data = nullptr;\n    }\n\n    return *this;\n}\n\n//==================================================================\n//\n//\t\tmembers\n//\n//==================================================================\n\nStrBlobPtr StrBlob::begin()\n{\n    return StrBlobPtr(*this);\n}\n\nStrBlobPtr StrBlob::end()\n{\n    return StrBlobPtr(*this, data->size());\n}\n\nConstStrBlobPtr StrBlob::cbegin() const\n{\n    return ConstStrBlobPtr(*this);\n}\n\nConstStrBlobPtr StrBlob::cend() const\n{\n    return ConstStrBlobPtr(*this, data->size());\n}\n"
  },
  {
    "path": "ch14/ex14_27_28_StrBlob.h",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nStrBlob, StrBlobPtr, ConstStrBlobPtr\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#ifndef CP5_STRBLOB_H_\n#define CP5_STRBLOB_H_\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <initializer_list>\nusing std::initializer_list;\n\n#include <memory>\nusing std::make_shared; using std::shared_ptr;\n\n#include <exception>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrBlobPtr;\nclass ConstStrBlobPtr;\n\n//=================================================================================\n//\n//\t\tStrBlob - custom vector<string>\n//\n//=================================================================================\n\nclass StrBlob {\n    using size_type = vector<string>::size_type;\n    friend class ConstStrBlobPtr;\n    friend class StrBlobPtr;\n    friend bool operator==(const StrBlob&, const StrBlob&);\n    friend bool operator!=(const StrBlob&, const StrBlob&);\n    friend bool operator< (const StrBlob&, const StrBlob&);\n    friend bool operator> (const StrBlob&, const StrBlob&);\n    friend bool operator<=(const StrBlob&, const StrBlob&);\n    friend bool operator>=(const StrBlob&, const StrBlob&);\n\npublic:\n    StrBlob() : data(make_shared<vector<string>>()) { }\n    StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) { }\n\n    StrBlob(const StrBlob &sb) : data(make_shared<vector<string>>(*sb.data)) { }\n    StrBlob& operator=(const StrBlob&);\n\n    StrBlob(StrBlob &&rhs) NOEXCEPT : data(std::move(rhs.data)) { }\n    StrBlob& operator=(StrBlob &&)NOEXCEPT;\n\n    StrBlobPtr begin();\n    StrBlobPtr end();\n\n    ConstStrBlobPtr cbegin() const;\n    ConstStrBlobPtr cend() const;\n\n    string& operator[](size_t n);\n    const string& operator[](size_t n) const;\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void push_back(string &&s) { data->push_back(std::move(s)); }\n\n    void pop_back();\n    string& front();\n    string& back();\n    const string& front() const;\n    const string& back() const;\n\nprivate:\n    void check(size_type, const string&) const;\n\n    shared_ptr<vector<string>> data;\n};\n\nbool operator==(const StrBlob&, const StrBlob&);\nbool operator!=(const StrBlob&, const StrBlob&);\nbool operator< (const StrBlob&, const StrBlob&);\nbool operator> (const StrBlob&, const StrBlob&);\nbool operator<=(const StrBlob&, const StrBlob&);\nbool operator>=(const StrBlob&, const StrBlob&);\n\ninline void StrBlob::pop_back()\n{\n    check(0, \"pop_back on empty StrBlob\");\n    data->pop_back();\n}\n\ninline string& StrBlob::front()\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline string& StrBlob::back()\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline const string& StrBlob::front() const\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline const string& StrBlob::back() const\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline void StrBlob::check(size_type i, const string &msg) const\n{\n    if (i >= data->size()) throw std::out_of_range(msg);\n}\n\ninline string& StrBlob::operator[](size_t n)\n{\n    check(n, \"out of range\");\n    return data->at(n);\n}\n\ninline const string& StrBlob::operator[](size_t n) const\n{\n    check(n, \"out of range\");\n    return data->at(n);\n}\n\n//=================================================================================\n//\n//\t\tStrBlobPtr - custom iterator of StrBlob\n//\n//=================================================================================\n\nclass StrBlobPtr {\n    friend bool operator==(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator!=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator< (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator> (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator<=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\npublic:\n    StrBlobPtr() : curr(0) { }\n    StrBlobPtr(StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    string& deref() const;\n    StrBlobPtr& operator++();\n    StrBlobPtr& operator--();\n    StrBlobPtr operator++(int);\n    StrBlobPtr operator--(int);\n    StrBlobPtr& operator+=(size_t);\n    StrBlobPtr& operator-=(size_t);\n    StrBlobPtr operator+(size_t) const;\n    StrBlobPtr operator-(size_t) const;\n\n    string& operator[](size_t n);\n    const string& operator[](size_t n) const;\n\nprivate:\n    shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const StrBlobPtr&, const StrBlobPtr&);\nbool operator!=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator< (const StrBlobPtr&, const StrBlobPtr&);\nbool operator> (const StrBlobPtr&, const StrBlobPtr&);\nbool operator<=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\ninline string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline StrBlobPtr& StrBlobPtr::operator++()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline StrBlobPtr& StrBlobPtr::operator--()\n{\n    check(--curr, \"decrement past begin of StrBlobPtr\");\n    return *this;\n}\n\ninline StrBlobPtr StrBlobPtr::operator++(int)\n{\n    StrBlobPtr ret = *this;\n    ++*this;\n    return ret;\n}\n\ninline StrBlobPtr StrBlobPtr::operator--(int)\n{\n    StrBlobPtr ret = *this;\n    --*this;\n    return ret;\n}\n\ninline StrBlobPtr& StrBlobPtr::operator+=(size_t n)\n{\n    curr += n;\n    check(curr, \"increment past end of StrBlobPtr\");\n    return *this;\n}\n\ninline StrBlobPtr& StrBlobPtr::operator-=(size_t n)\n{\n    curr -= n;\n    check(curr, \"increment past end of StrBlobPtr\");\n    return *this;\n}\n\ninline StrBlobPtr StrBlobPtr::operator+(size_t n) const\n{\n    StrBlobPtr ret = *this;\n    ret += n;\n    return ret;\n}\n\ninline StrBlobPtr StrBlobPtr::operator-(size_t n) const\n{\n    StrBlobPtr ret = *this;\n    ret -= n;\n    return ret;\n}\n\ninline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\ninline string& StrBlobPtr::operator[](size_t n)\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\ninline const string& StrBlobPtr::operator[](size_t n) const\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\n//=================================================================================\n//\n//\t\tConstStrBlobPtr - custom const_iterator of StrBlob\n//\n//=================================================================================\n\nclass ConstStrBlobPtr {\n    friend bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\npublic:\n    ConstStrBlobPtr() : curr(0) { }\n    ConstStrBlobPtr(const StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    const string& deref() const;\n    ConstStrBlobPtr& operator++();\n    ConstStrBlobPtr& operator--();\n    ConstStrBlobPtr operator++(int);\n    ConstStrBlobPtr operator--(int);\n    ConstStrBlobPtr& operator+=(size_t);\n    ConstStrBlobPtr& operator-=(size_t);\n    ConstStrBlobPtr operator+(size_t) const;\n    ConstStrBlobPtr operator-(size_t) const;\n\n    const string& operator[](size_t n) const;\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\ninline const string& ConstStrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator++()\n{\n    check(curr, \"increment past end of ConstStrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator--()\n{\n    --curr;\n    check(-1, \"decrement past begin of ConstStrBlobPtr\");\n    return *this;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator++(int)\n{\n    ConstStrBlobPtr ret = *this;\n    ++*this;\n    return ret;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator--(int)\n{\n    ConstStrBlobPtr ret = *this;\n    --*this;\n    return ret;\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator+=(size_t n)\n{\n    curr += n;\n    check(curr, \"increment past end of ConstStrBlobPtr\");\n    return *this;\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator-=(size_t n)\n{\n    curr -= n;\n    check(curr, \"increment past end of ConstStrBlobPtr\");\n    return *this;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator+(size_t n) const\n{\n    ConstStrBlobPtr ret = *this;\n    ret += n;\n    return ret;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator-(size_t n) const\n{\n    ConstStrBlobPtr ret = *this;\n    ret -= n;\n    return ret;\n}\n\ninline std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\ninline const string& ConstStrBlobPtr::operator[](size_t n) const\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\n#endif //CP5_STRBLOB_H_\n"
  },
  {
    "path": "ch14/ex14_27_28_StrBlobTest.cpp",
    "content": "#include \"ex14_27_28_StrBlob.h\"\n#include <iostream>\n\nint main()\n{\n    StrBlob sb1{ \"a\", \"b\", \"c\" };\n    StrBlob sb2 = sb1;\n\n    sb2[2] = \"b\";\n\n    if (sb1 > sb2) {\n        for (StrBlobPtr iter = sb1.begin(); iter < sb1.end(); ++iter)\n            std::cout << iter.deref() << \" \";\n        std::cout << std::endl;\n    }\n\n    ConstStrBlobPtr iter(sb2);\n    std::cout << (iter + 2).deref() << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_30_StrBlob.cpp",
    "content": "#include \"ex14_30_StrBlob.h\"\n#include <algorithm>\n\n//==================================================================\n//\n//\t\tStrBlob - operators\n//\n//==================================================================\n\nbool operator==(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return *lhs.data == *rhs.data;\n}\n\nbool operator!=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());\n}\n\nbool operator> (const StrBlob &lhs, const StrBlob &rhs)\n{\n    return rhs < lhs;\n}\n\nbool operator<=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(rhs < lhs);\n}\n\nbool operator>=(const StrBlob &lhs, const StrBlob &rhs)\n{\n    return !(lhs < rhs);\n}\n\n//================================================================\n//\n//\t\tStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr < y.curr;\n}\n\nbool operator>(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr > y.curr;\n}\n\nbool operator<=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr <= y.curr;\n}\n\nbool operator>=(const StrBlobPtr &x, const StrBlobPtr &y)\n{\n    return x.curr >= y.curr;\n}\n\n//================================================================\n//\n//\t\tConstStrBlobPtr - operators\n//\n//================================================================\n\nbool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr == rhs.curr;\n}\n\nbool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return !(lhs == rhs);\n}\n\nbool operator< (const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr < rhs.curr;\n}\n\nbool operator>(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr > rhs.curr;\n}\n\nbool operator<=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr <= rhs.curr;\n}\n\nbool operator>=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)\n{\n    return lhs.curr >= rhs.curr;\n}\n\n//==================================================================\n//\n//\t\tcopy assignment operator and move assignment operator.\n//\n//==================================================================\n\nStrBlob& StrBlob::operator=(const StrBlob &lhs)\n{\n    data = make_shared<vector<string>>(*lhs.data);\n    return *this;\n}\n\nStrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT\n{\n    if (this != &rhs) {\n        data = std::move(rhs.data);\n        rhs.data = nullptr;\n    }\n\n    return *this;\n}\n\n//==================================================================\n//\n//\t\tmembers\n//\n//==================================================================\n\nStrBlobPtr StrBlob::begin()\n{\n    return StrBlobPtr(*this);\n}\n\nStrBlobPtr StrBlob::end()\n{\n    return StrBlobPtr(*this, data->size());\n}\n\nConstStrBlobPtr StrBlob::cbegin() const\n{\n    return ConstStrBlobPtr(*this);\n}\n\nConstStrBlobPtr StrBlob::cend() const\n{\n    return ConstStrBlobPtr(*this, data->size());\n}\n"
  },
  {
    "path": "ch14/ex14_30_StrBlob.h",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nStrBlob, StrBlobPtr, ConstStrBlobPtr\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#ifndef CP5_STRBLOB_H_\n#define CP5_STRBLOB_H_\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <initializer_list>\nusing std::initializer_list;\n\n#include <memory>\nusing std::make_shared; using std::shared_ptr;\n\n#include <exception>\n\n#ifndef _MSC_VER\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\nclass StrBlobPtr;\nclass ConstStrBlobPtr;\n\n//=================================================================================\n//\n//\t\tStrBlob - custom vector<string>\n//\n//=================================================================================\n\nclass StrBlob {\n    using size_type = vector<string>::size_type;\n    friend class ConstStrBlobPtr;\n    friend class StrBlobPtr;\n    friend bool operator==(const StrBlob&, const StrBlob&);\n    friend bool operator!=(const StrBlob&, const StrBlob&);\n    friend bool operator< (const StrBlob&, const StrBlob&);\n    friend bool operator> (const StrBlob&, const StrBlob&);\n    friend bool operator<=(const StrBlob&, const StrBlob&);\n    friend bool operator>=(const StrBlob&, const StrBlob&);\n\npublic:\n    StrBlob() : data(make_shared<vector<string>>()) { }\n    StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) { }\n\n    StrBlob(const StrBlob &sb) : data(make_shared<vector<string>>(*sb.data)) { }\n    StrBlob& operator=(const StrBlob&);\n\n    StrBlob(StrBlob &&rhs) NOEXCEPT : data(std::move(rhs.data)) { }\n    StrBlob& operator=(StrBlob &&)NOEXCEPT;\n\n    StrBlobPtr begin();\n    StrBlobPtr end();\n\n    ConstStrBlobPtr cbegin() const;\n    ConstStrBlobPtr cend() const;\n\n    string& operator[](size_t n);\n    const string& operator[](size_t n) const;\n\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    void push_back(const string &t) { data->push_back(t); }\n    void push_back(string &&s) { data->push_back(std::move(s)); }\n\n    void pop_back();\n    string& front();\n    string& back();\n    const string& front() const;\n    const string& back() const;\n\nprivate:\n    void check(size_type, const string&) const;\n\n    shared_ptr<vector<string>> data;\n};\n\nbool operator==(const StrBlob&, const StrBlob&);\nbool operator!=(const StrBlob&, const StrBlob&);\nbool operator< (const StrBlob&, const StrBlob&);\nbool operator> (const StrBlob&, const StrBlob&);\nbool operator<=(const StrBlob&, const StrBlob&);\nbool operator>=(const StrBlob&, const StrBlob&);\n\ninline void StrBlob::pop_back()\n{\n    check(0, \"pop_back on empty StrBlob\");\n    data->pop_back();\n}\n\ninline string& StrBlob::front()\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline string& StrBlob::back()\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline const string& StrBlob::front() const\n{\n    check(0, \"front on empty StrBlob\");\n    return data->front();\n}\n\ninline const string& StrBlob::back() const\n{\n    check(0, \"back on empty StrBlob\");\n    return data->back();\n}\n\ninline void StrBlob::check(size_type i, const string &msg) const\n{\n    if (i >= data->size()) throw std::out_of_range(msg);\n}\n\ninline string& StrBlob::operator[](size_t n)\n{\n    check(n, \"out of range\");\n    return data->at(n);\n}\n\ninline const string& StrBlob::operator[](size_t n) const\n{\n    check(n, \"out of range\");\n    return data->at(n);\n}\n\n//=================================================================================\n//\n//\t\tStrBlobPtr - custom iterator of StrBlob\n//\n//=================================================================================\n\nclass StrBlobPtr {\n    friend bool operator==(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator!=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator< (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator> (const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator<=(const StrBlobPtr&, const StrBlobPtr&);\n    friend bool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\npublic:\n    StrBlobPtr() : curr(0) { }\n    StrBlobPtr(StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    string& deref() const;\n    StrBlobPtr& operator++();\n    StrBlobPtr& operator--();\n    StrBlobPtr operator++(int);\n    StrBlobPtr operator--(int);\n    StrBlobPtr& operator+=(size_t);\n    StrBlobPtr& operator-=(size_t);\n    StrBlobPtr operator+(size_t) const;\n    StrBlobPtr operator-(size_t) const;\n\n    string& operator[](size_t n);\n    const string& operator[](size_t n) const;\n\nprivate:\n    shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const StrBlobPtr&, const StrBlobPtr&);\nbool operator!=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator< (const StrBlobPtr&, const StrBlobPtr&);\nbool operator> (const StrBlobPtr&, const StrBlobPtr&);\nbool operator<=(const StrBlobPtr&, const StrBlobPtr&);\nbool operator>=(const StrBlobPtr&, const StrBlobPtr&);\n\ninline string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline StrBlobPtr& StrBlobPtr::operator++()\n{\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline StrBlobPtr& StrBlobPtr::operator--()\n{\n    --curr;\n    check(-1, \"decrement past begin of StrBlobPtr\");\n    return *this;\n}\n\ninline StrBlobPtr StrBlobPtr::operator++(int)\n{\n    StrBlobPtr ret = *this;\n    ++*this;\n    return ret;\n}\n\ninline StrBlobPtr StrBlobPtr::operator--(int)\n{\n    StrBlobPtr ret = *this;\n    --*this;\n    return ret;\n}\n\ninline StrBlobPtr& StrBlobPtr::operator+=(size_t n)\n{\n    curr += n;\n    check(curr, \"increment past end of StrBlobPtr\");\n    return *this;\n}\n\ninline StrBlobPtr& StrBlobPtr::operator-=(size_t n)\n{\n    curr -= n;\n    check(curr, \"increment past end of StrBlobPtr\");\n    return *this;\n}\n\ninline StrBlobPtr StrBlobPtr::operator+(size_t n) const\n{\n    StrBlobPtr ret = *this;\n    ret += n;\n    return ret;\n}\n\ninline StrBlobPtr StrBlobPtr::operator-(size_t n) const\n{\n    StrBlobPtr ret = *this;\n    ret -= n;\n    return ret;\n}\n\ninline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\ninline string& StrBlobPtr::operator[](size_t n)\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\ninline const string& StrBlobPtr::operator[](size_t n) const\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\n//=================================================================================\n//\n//\t\tConstStrBlobPtr - custom const_iterator of StrBlob\n//\n//=================================================================================\n\nclass ConstStrBlobPtr {\n    friend bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n    friend bool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\npublic:\n    ConstStrBlobPtr() : curr(0) { }\n    ConstStrBlobPtr(const StrBlob &s, size_t sz = 0) : wptr(s.data), curr(sz) { }\n\n    const string& operator*() const;\n    const string* operator->() const;\n    ConstStrBlobPtr& operator++();\n    ConstStrBlobPtr& operator--();\n    ConstStrBlobPtr operator++(int);\n    ConstStrBlobPtr operator--(int);\n    ConstStrBlobPtr& operator+=(size_t);\n    ConstStrBlobPtr& operator-=(size_t);\n    ConstStrBlobPtr operator+(size_t) const;\n    ConstStrBlobPtr operator-(size_t) const;\n\n    const string& operator[](size_t n) const;\n\nprivate:\n    std::shared_ptr<vector<string>> check(size_t, const string&) const;\n\n    std::weak_ptr<vector<string>> wptr;\n    size_t curr;\n};\n\nbool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\nbool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);\n\ninline const string& ConstStrBlobPtr::operator*() const\n{\n    auto p = check(curr, \"dereference past end\");\n    return (*p)[curr];\n}\n\ninline const string* ConstStrBlobPtr::operator->() const\n{\n    return &this->operator*();\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator++()\n{\n    check(curr, \"increment past end of ConstStrBlobPtr\");\n    ++curr;\n    return *this;\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator--()\n{\n    --curr;\n    check(-1, \"decrement past begin of ConstStrBlobPtr\");\n    return *this;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator++(int)\n{\n    ConstStrBlobPtr ret = *this;\n    ++*this;\n    return ret;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator--(int)\n{\n    ConstStrBlobPtr ret = *this;\n    --*this;\n    return ret;\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator+=(size_t n)\n{\n    curr += n;\n    check(curr, \"increment past end of ConstStrBlobPtr\");\n    return *this;\n}\n\ninline ConstStrBlobPtr& ConstStrBlobPtr::operator-=(size_t n)\n{\n    curr -= n;\n    check(curr, \"increment past end of ConstStrBlobPtr\");\n    return *this;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator+(size_t n) const\n{\n    ConstStrBlobPtr ret = *this;\n    ret += n;\n    return ret;\n}\n\ninline ConstStrBlobPtr ConstStrBlobPtr::operator-(size_t n) const\n{\n    ConstStrBlobPtr ret = *this;\n    ret -= n;\n    return ret;\n}\n\ninline std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const\n{\n    auto ret = wptr.lock();\n    if (!ret) throw std::runtime_error(\"unbound StrBlobPtr\");\n    if (i >= ret->size()) throw std::out_of_range(msg);\n    return ret;\n}\n\ninline const string& ConstStrBlobPtr::operator[](size_t n) const\n{\n    auto p = check(n, \"dereference out of range.\");\n    return (*p)[n];\n}\n\n#endif //CP5_STRBLOB_H_\n"
  },
  {
    "path": "ch14/ex14_30_StrBlobTest.cpp",
    "content": "#include \"ex14_30_StrBlob.h\"\n#include <iostream>\n\nint main()\n{\n    StrBlob sb1{ \"a\", \"b\", \"c\" };\n    StrBlob sb2 = sb1;\n\n    sb2[2] = \"b\";\n\n    if (sb1 > sb2) {\n        for (ConstStrBlobPtr iter = sb1.cbegin(); iter != sb1.cend(); ++iter)\n            std::cout << *iter << \" \";\n        std::cout << std::endl;\n    }\n\n    ConstStrBlobPtr iter(sb2);\n    std::cout << iter->size() << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_32.cpp",
    "content": "#include \"ex14_32.h\"\n#include \"ex14_30_StrBlob.h\"\n#include <iostream>\n\nStrBlobPtr&\nStrBlobPtr_pointer::operator *() const\n{\n    return *pointer;\n}\n\nStrBlobPtr*\nStrBlobPtr_pointer::operator ->() const\n{\n    return pointer;\n}\n\nint main()\n{\n    StrBlob sb{ \"hello\", \"world\" };\n    StrBlobPtr iter = sb.begin();\n    StrBlobPtr_pointer p(&iter);\n    std::cout << p->deref() << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_32.h",
    "content": "/***************************************************************************\n *  @file       StrBlobPtr_pointer.h\n *  @author     Alan.W\n *  @date       19  JAN 2014\n *  @remark     a class that holds a pointer to a StrBlobPtr.\n ***************************************************************************/\n\n#ifndef STRBLOBPTR_POINTER_H\n#define STRBLOBPTR_POINTER_H\n\nclass StrBlobPtr;\n\n/**\n * @brief a class that holds a pointer to a StrBlobPtr.\n */\nclass StrBlobPtr_pointer\n{\npublic:\n    StrBlobPtr_pointer() = default;\n    StrBlobPtr_pointer(StrBlobPtr* p) : pointer(p) { }\n\n    StrBlobPtr& operator *() const;\n    StrBlobPtr* operator->() const;\n\nprivate:\n    StrBlobPtr* pointer = nullptr;\n};\n\n#endif // STRBLOBPTR_POINTER_H\n"
  },
  {
    "path": "ch14/ex14_35.cpp",
    "content": "#include <iostream>\n#include <string>\n\nclass GetInput {\npublic:\n    GetInput(std::istream &i = std::cin) : is(i) { }\n    std::string operator()() const {\n        std::string str;\n        std::getline(is, str);\n        return is ? str : std::string();\n    }\n\nprivate:\n    std::istream &is;\n};\n\nint main()\n{\n    GetInput getInput;\n    std::cout << getInput() << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_36.cpp",
    "content": "#include <iostream>\n#include <string>\n#include <vector>\n\nclass GetInput {\npublic:\n    GetInput(std::istream &i = std::cin) : is(i) { }\n    std::string operator()() const {\n        std::string str;\n        std::getline(is, str);\n        return is ? str : std::string();\n    }\n\nprivate:\n    std::istream &is;\n};\n\nint main()\n{\n    GetInput getInput;\n    std::vector<std::string> vec;\n    for ( std::string tmp; !( tmp = getInput() ).empty(); ) vec.push_back( tmp );\n    for (const auto &str : vec) std::cout << str << \" \";\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_37.cpp",
    "content": "#include <iostream>\n#include <vector>\n#include <algorithm>\n\nclass IsEqual {\n    int value;\npublic:\n    IsEqual(int v) : value(v) { }\n    bool operator()(int elem) {\n        return elem == value;\n    }\n};\n\nint main()\n{\n    std::vector<int> vec = { 3, 2, 1, 4, 3, 7, 8, 6 };\n    std::replace_if(vec.begin(), vec.end(), IsEqual(3), 5);\n    for (int i : vec) std::cout << i << \" \";\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_38_39.cpp",
    "content": "//\n// Exercise 14.38:\n// Write a class that tests whether the length of a given string matches a\n// given bound. Use that object to write a program to report how many words\n// in an input file are of sizes 1 through 10 inclusive.\n//\n// Exercise 14.39:\n// Revise the previous program to report the count of words that are sizes\n// 1 through 9 and 10 or more.\n//\n\n#include <iostream>\n#include <string>\n#include <fstream>\n#include <vector>\n#include <map>\n\nstruct IsInRange\n{\n    IsInRange(std::size_t lower, std::size_t upper)\n        :_lower(lower), _upper(upper)\n    { }\n\n    bool operator()(std::string const& str) const\n    {\n        return str.size() >= _lower && str.size() <= _upper;\n    }\n\n    std::size_t lower_limit() const\n    {\n        return _lower;\n    }\n\n    std::size_t upper_limit() const\n    {\n        return _upper;\n    }\nprivate:\n    std::size_t _lower;\n    std::size_t _upper;\n};\n\nint main()\n{\n    //create predicates with various upper limits.\n    std::size_t lower = 1;\n    auto uppers = { 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u };\n    std::vector<IsInRange> predicates;\n    for (auto upper : uppers)\n        predicates.push_back(IsInRange{ lower, upper });\n\n    //create count_table to store counts \n    std::map<std::size_t, std::size_t> count_table;\n    for (auto upper : uppers)\n        count_table[upper] = 0;\n\n    //read file and count\n    std::ifstream fin(\"../data/storyDataFile.txt\");\n    for (std::string word; fin >> word; /* */)\n        for (auto is_size_in_range : predicates)\n            if (is_size_in_range(word))\n                ++count_table[is_size_in_range.upper_limit()];\n\n    //print\n    for (auto pair : count_table)\n        std::cout << \"count in range [1, \" << pair.first << \"] : \" << pair.second << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch14/ex14_40.cpp",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nRewrite the `biggies` function to use function-object classes in place of lambdas\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <iostream>\nusing std::cout; using std::endl;\n\n#include <algorithm>\nusing std::sort; using std::stable_sort; using std::for_each;\n\nclass ShorterString {\npublic:\n    bool operator()(string const& s1, string const& s2) const { return s1.size() < s2.size(); }\n};\n\nclass BiggerEqual {\n    size_t sz_;\npublic:\n    BiggerEqual(size_t sz) : sz_(sz) { }\n    bool operator()(string const& s) { return s.size() >= sz_; }\n};\n\nclass Print {\npublic:\n    void operator()(string const& s) { cout << s << \" \"; }\n};\n\nstring make_plural(size_t ctr, string const& word, string const& ending)\n{\n    return (ctr > 1) ? word + ending : word;\n}\n\nvoid elimDups(vector<string> &words) {\n    sort(words.begin(), words.end());\n    auto end_unique = unique(words.begin(), words.end());\n    words.erase(end_unique, words.end());\n}\n\nvoid biggies( vector<string> &words, vector<string>::size_type sz ) {\n    elimDups(words);\n    stable_sort(words.begin(), words.end(), ShorterString());\n    auto wc = find_if(words.begin(), words.end(), BiggerEqual(sz));\n    auto count = words.end() - wc;\n    cout << count << \" \" << make_plural(count, \"word\", \"s\") << \" of length \" << sz << \" or longer\" << endl;\n    for_each(wc, words.end(), Print());\n    cout << endl;\n}\n\nint main()\n{\n    vector<string> vec{ \"fox\", \"jumps\", \"over\", \"quick\", \"red\", \"red\", \"slow\", \"the\", \"turtle\" };\n    biggies(vec, 4);\n}\n"
  },
  {
    "path": "ch14/ex14_42.cpp",
    "content": "#include <algorithm>\n#include <vector>\n#include <string>\n#include <iostream>\n#include <functional>\n\nint main()\n{\n    using std::placeholders::_1;\n\n    std::vector<int> ivec { 1, 111, 1111, 11111 };\n    int count = std::count_if (ivec.cbegin(), ivec.cend(), std::bind(std::greater<int>(), _1, 1024));\n    std::cout << count << std::endl;\n\n    std::vector<std::string> svec { \"pooh\", \"pooh\", \"pezy\", \"pooh\" };\n    auto found = std::find_if (svec.cbegin(), svec.cend(), std::bind(std::not_equal_to<std::string>(), _1, \"pooh\"));\n    std::cout << *found << std::endl;\n\n    std::transform(ivec.begin(), ivec.end(), ivec.begin(), std::bind(std::multiplies<int>(), _1, 2));\n    for (int i : ivec) std::cout << i << \" \";\n    std::cout << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_43.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     XDXX， Yue Wang\n *  @date       5/24/2015\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 14.43:\n// Using library function objects, determine whether a given int value is\n// divisible by any element in a container of ints.\n//\n\n#include <iostream>\n#include <string>\n#include <functional>\n#include <algorithm>\n\nint main()\n{\n    auto data = { 2, 3, 4, 5 };\n    int input;\n    std::cin >> input;\n    std::modulus<int> mod;\n    auto predicator = [&](int i){ return 0 == mod(input, i); };\n    auto is_divisible = std::any_of(data.begin(), data.end(), predicator);\n    std::cout << (is_divisible ? \"Yes!\" : \"No!\") << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch14/ex14_44.cpp",
    "content": "/***************************************************************************\n*  @file       ex14_44.cpp\n*  @author     Yue Wang\n*  @date       21  Jan 2014\n*              17  Jun 2015  \n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 14.44:\n// Write your own version of a simple desk calculator that can handle binary operations.\n//\n\n#include <iostream>\n#include <string>\n#include <map> \n#include <functional> \n\nint add(int i, int j){ return i + j; }\nauto mod = [](int i, int j){ return i % j; };\nstruct Div{ int operator ()(int i, int j) const { return i / j; } };\n\nauto binops = std::map<std::string, std::function<int(int, int)>>\n{\n    { \"+\", add },                               // function pointer \n    { \"-\", std::minus<int>() },                 // library functor \n    { \"/\", Div() },                             // user-defined functor \n    { \"*\", [](int i, int j) { return i*j; } },  // unnamed lambda \n    { \"%\", mod }                                // named lambda object \n};\n\n\nint main()\n{\n    while ( std::cout << \"Pls enter as: num operator num :\\n\", true )\n    {\n        int lhs, rhs; std::string op;\n        std::cin >> lhs >> op >> rhs;\n        std::cout << binops[op](lhs, rhs) << std::endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch14/ex14_45.cpp",
    "content": "#include \"ex14_45.h\"\n\nSales_data::Sales_data(std::istream &is) : Sales_data()\n{\n    is >> *this;\n}\n\nSales_data& Sales_data::operator+=(const Sales_data &rhs)\n{\n    units_sold += rhs.units_sold;\n    revenue += rhs.revenue;\n    return *this;\n}\n\nstd::istream& operator>>(std::istream &is, Sales_data &item)\n{\n    double price = 0.0;\n    is >> item.bookNo >> item.units_sold >> price;\n    if (is)\n        item.revenue = price * item.units_sold;\n    else\n        item = Sales_data();\n    return is;\n}\n\nstd::ostream& operator<<(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \" << item.revenue << \" \" << item.avg_price();\n    return os;\n}\n\nSales_data operator+(const Sales_data &lhs, const Sales_data &rhs)\n{\n    Sales_data sum = lhs;\n    sum += rhs;\n    return sum;\n}\n\nSales_data& Sales_data::operator=(const std::string &isbn)\n{\n    *this = Sales_data(isbn);\n    return *this;\n}\n"
  },
  {
    "path": "ch14/ex14_45.h",
    "content": "/*\n=================================================================================\n\nC++ Primer 5th Exercise Answer Source Code\n\nSales_data\n\nIf you have questions, try to connect with me: pezy<urbancpz@gmail.com>\n\n=================================================================================\n*/\n\n#ifndef CP5_ex14_45_h\n#define CP5_ex14_45_h\n\n#include <string>\n#include <iostream>\n\nclass Sales_data {\n    friend std::istream& operator>>(std::istream&, Sales_data&);\n    friend std::ostream& operator<<(std::ostream&, const Sales_data&);\n    friend Sales_data operator+(const Sales_data&, const Sales_data&);\n\npublic:\n    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }\n    Sales_data() : Sales_data(\"\", 0, 0.0f){ }\n    Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f){ }\n    Sales_data(std::istream &is);\n\n    Sales_data& operator=(const std::string&);\n    Sales_data& operator+=(const Sales_data&);\n    explicit operator std::string() const { return bookNo; }\n    explicit operator double() const { return avg_price(); }\n\n    std::string isbn() const { return bookNo; }\n\nprivate:\n    inline double avg_price() const;\n\n    std::string bookNo;\n    unsigned units_sold = 0;\n    double revenue = 0.0;\n};\n\nstd::istream& operator>>(std::istream&, Sales_data&);\nstd::ostream& operator<<(std::ostream&, const Sales_data&);\nSales_data operator+(const Sales_data&, const Sales_data&);\n\ninline double Sales_data::avg_price() const\n{\n    return units_sold ? revenue/units_sold : 0;\n}\n\n#endif\n"
  },
  {
    "path": "ch14/ex14_45_TEST.cpp",
    "content": "#include \"ex14_45.h\"\n\nint main()\n{\n    Sales_data cp5(\"C++ Primer 5th\", 4, 106.5);\n    std::cout << cp5 << std::endl;\n    std::cout << static_cast<std::string>(cp5) << std::endl;\n    std::cout << static_cast<double>(cp5) << std::endl;\n}\n"
  },
  {
    "path": "ch14/ex14_49.cpp",
    "content": "#include \"ex14_49.h\"\n#include <algorithm>\n\n// constructor taking Size as days\n// the argument must be within (0, 2^32)\nDate::Date(Size days)\n{\n    // calculate the year\n    Size y400 =  days/YtoD_400;\n    Size y100 = (days - y400*YtoD_400)/YtoD_100;\n    Size y4   = (days - y400*YtoD_400 - y100*YtoD_100)/YtoD_4;\n    Size y    = (days - y400*YtoD_400 - y100*YtoD_100 - y4*YtoD_4)/365;\n    Size d    =  days - y400*YtoD_400 - y100*YtoD_100 - y4*YtoD_4 - y*365;\n    this->year = y400*400 + y100*100 + y4*4 + y;\n\n    // check if leap and choose the months vector accordingly\n    std::vector<Size>currYear\n            = isLeapYear(this->year) ? monthsVec_l : monthsVec_n;\n\n    // calculate day and month using find_if + lambda\n    Size D_accumu = 0, M_accumu = 0;\n    // @bug    fixed:  the variabbles above hade been declared inside the find_if as static\n    //                 which caused the bug. It works fine now after being move outside.\n\n    std::find_if(currYear.cbegin(), currYear.cend(), [&](Size m){\n\n        D_accumu += m;\n        M_accumu ++;\n\n        if(d < D_accumu)\n        {\n            this->month =   M_accumu;\n            this->day   =   d + m - D_accumu ;\n\n            return true;\n        }\n        else\n            return false;\n    });\n}\n\n// construcotr taking iostream\nDate::Date(std::istream &is, std::ostream &os)\n{\n    is >> day >> month >> year;\n\n    if(is)\n    {\n        if(check(*this)) return;\n        else\n        {\n            os << \"Invalid input! Object is default initialized.\";\n            *this = Date();\n        }\n    }\n    else\n    {\n        os << \"Invalid input! Object is default initialized.\";\n        *this = Date();\n    }\n\n}\n\n// copy constructor\nDate::Date(const Date &d) :\n    day(d.day), month(d.month), year(d.year)\n{ }\n\n// move constructor\nDate::Date(Date&& d) noexcept :\n    day(d.day), month(d.month), year(d.year)\n{ std::cout << \"copy moving\"; }\n\n// copy operator=\nDate &Date::operator= (const Date &d)\n{\n    this->day   = d.day;\n    this->month = d.month;\n    this->year  = d.year;\n\n    return *this;\n}\n\n// move operator=\nDate &Date::operator =(Date&& rhs) noexcept\n{\n    if(this != &rhs)\n    {\n        this->day   = rhs.day;\n        this->month = rhs.month;\n        this->year  = rhs.year;\n    }\n    std::cout << \"moving =\";\n\n    return *this;\n}\n\n// conver to days\nDate::Size Date::toDays() const\n{\n    Size result = this->day;\n\n    // check if leap and choose the months vector accordingly\n    std::vector<Size>currYear\n            = isLeapYear(this->year) ? monthsVec_l : monthsVec_n;\n\n    // calculate result + days by months\n    for(auto it = currYear.cbegin(); it != currYear.cbegin() + this->month -1; ++it)\n        result += *it;\n\n    // calculate result + days by years\n    result += (this->year/400)      * YtoD_400;\n    result += (this->year%400/100)  * YtoD_100;\n    result += (this->year%100/4)    * YtoD_4;\n    result += (this->year%4)        * YtoD_1;\n\n    return result;\n}\n\n// member operators:   +=  -=\n\nDate &Date::operator +=(Date::Size offset)\n{\n    *this = Date(this->toDays() + offset);\n    return *this;\n}\n\nDate &Date::operator -=(Date::Size offset)\n{\n    if(this->toDays() > offset)\n        *this = Date(this->toDays() - offset);\n    else\n        *this = Date();\n\n    return *this;\n}\n\n// non-member operators:  <<  >>  -   ==  !=  <   <=  >   >=\n\nstd::ostream&\noperator <<(std::ostream& os, const Date& d)\n{\n    os << d.day << \" \" << d.month << \" \" << d.year;\n    return os;\n}\n\nstd::istream&\noperator >>(std::istream& is, Date& d)\n{\n    if(is)\n    {\n        Date input = Date(is, std::cout);\n        if(check(input))    d = input;\n    }\n    return is;\n}\n\n\nint operator -(const Date &lhs, const Date &rhs)\n{\n    return lhs.toDays() - rhs.toDays();\n}\n\n\nbool operator ==(const Date &lhs, const Date &rhs)\n{\n    return (lhs.day   == rhs.day  ) &&\n           (lhs.month == rhs.month) &&\n           (lhs.year  == rhs.year )    ;\n}\n\n\nbool operator !=(const Date &lhs, const Date &rhs)\n{\n    return !(lhs == rhs);\n}\n\n\nbool operator < (const Date &lhs, const Date &rhs)\n{\n    return lhs.toDays() < rhs.toDays();\n}\n\n\nbool operator <=(const Date &lhs, const Date &rhs)\n{\n    return (lhs < rhs) || (lhs == rhs);\n}\n\n\nbool operator >(const Date &lhs, const Date &rhs)\n{\n    return !(lhs <= rhs);\n}\n\n\nbool operator >=(const Date &lhs, const Date &rhs)\n{\n    return !(lhs < rhs);\n}\n\n\nDate operator - (const Date &lhs, Date::Size rhs)\n{                                       //  ^^^ rhs must not be larger than 2^32-1\n    // copy lhs\n    Date result(lhs);\n    result -= rhs;\n\n    return result;\n}\n\n\nDate operator + (const Date &lhs, Date::Size rhs)\n{                                       //  ^^^ rhs must not be larger than 2^32-1\n    // copy lhs\n    Date result(lhs);\n    result += rhs;\n\n    return result;\n}\n"
  },
  {
    "path": "ch14/ex14_49.h",
    "content": "/***************************************************************************\n *  @file       date.h\n *  @author     Alan.W\n *  @date       15-17  JAN 2014\n *  @remark\n ***************************************************************************/\n//\n// Exercise 7.40:\n// Choose one of the following abstractions (or an abstraction of your own choosing).\n// Determine what data are needed in the class. Provide an appropriate set of constructors.\n// Explain your decisions.\n//\n// Exercise 14.5:\n// In exercise 7.40 from § 7.5.1 (p. 291) you wrote a sketch of one of the\n// following classes. Decide what, if any, overloaded operators your class\n// should provide.\n//      -   =   <   >   <=  >=  ++  --  <<  >>  ==  !=  +=  -=\n// Exercise 14.8:\n// Define an output operator for the class you chose in exercise 7.40 from\n// § 7.5.1 (p. 291).\n//\n// Exercise 14.12:\n// Define an input operator for the class you used in exercise 7.40 from\n// § 7.5.1 (p. 291). Be sure the operator handles input errors.\n//\n// Exercise 14.15:\n// Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291)\n// define any of the arithmetic operators? If so, implement them.\n// If not, explain why not.\n//\n//      arithmetic operators :  all non-members\n//      +   :   Date + Size\n//      -   :   Date - Size\n//      -   :   Date - Date\n//\n// Exercise 14.17:\n// Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291) define\n// the equality operators? If so, implement them. If not, explain why not.\n//\n// Exercise 14.19:\n// Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291) define\n// the relational operators? If so, implement them. If not, explain why not.\n//\n// Exercise 14.25:\n// Implement any other assignment operators your class should define.\n// Explain which types should be used as operands and why.\n//\n// Exercise 14.49:\n// Regardless of whether it is a good idea to do so, define a conversion to bool\n// for the class from the previous exercise.\n//\n\n#ifndef DATE_H\n#define DATE_H\n\n#include <iostream>\n#include <vector>\n\nclass Date\n{\n    friend  bool            operator ==(const Date& lhs, const Date& rhs);\n    friend  bool            operator < (const Date &lhs, const Date &rhs);\n    friend  bool            check(const Date &d);\n    friend  std::ostream&   operator <<(std::ostream& os, const Date& d);\npublic:\n    typedef std::size_t Size;\n\n    // default constructor\n    Date() = default;\n    // constructor taking Size as days\n    explicit Date(Size days);\n    // constructor taking three Size\n    Date(Size d, Size m, Size y) : day(d), month(m), year(y) { }\n    // constructor taking iostream\n    Date(std::istream &is, std::ostream &os);\n\n    // copy constructor\n    Date(const Date& d);\n    // move constructor\n    Date(Date&& d) noexcept;\n\n    // copy operator=\n    Date& operator= (const Date& d);\n    // move operator=\n    Date& operator= (Date&& rhs) noexcept;\n\n    // destructor  --  in this case, user-defined destructor is not nessary.\n    ~Date(){ std::cout << \"destroying\\n\"; }\n\n    // members\n    Size toDays() const;  //not implemented yet.\n    Date& operator +=(Size offset);\n    Date& operator -=(Size offset);\n    explicit operator bool() { return (year<4000) ? true : false; }\n\nprivate:\n    Size    day = 1;\n    Size    month = 1;\n    Size    year = 0;\n};\n\nstatic const Date::Size YtoD_400 = 146097;    //365*400 + 400/4 -3 == 146097\nstatic const Date::Size YtoD_100 =  36524;    //365*100 + 100/4 -1 ==  36524\nstatic const Date::Size YtoD_4   =   1461;    //365*4 + 1          ==   1461\nstatic const Date::Size YtoD_1   =    365;    //365\n\n// normal year\nstatic const std::vector<Date::Size> monthsVec_n =\n{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n\n// leap year\nstatic const std::vector<Date::Size> monthsVec_l =\n{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n\n// non-member operators:  <<  >>  -   ==  !=  <   <=  >   >=\n//\nstd::ostream&\noperator <<(std::ostream& os, const Date& d);\nstd::istream&\noperator >>(std::istream& is, Date& d);\nint\noperator - (const Date& lhs, const Date& rhs);\nbool\noperator ==(const Date& lhs, const Date& rhs);\nbool\noperator !=(const Date& lhs, const Date& rhs);\nbool\noperator < (const Date& lhs, const Date& rhs);\nbool\noperator <=(const Date& lhs, const Date& rhs);\nbool\noperator  >(const Date& lhs, const Date& rhs);\nbool\noperator >=(const Date& lhs, const Date& rhs);\nDate\noperator - (const Date& lhs, Date::Size  rhs);\nDate\noperator  +(const Date& lhs, Date::Size  rhs);\n\n\n\n//  utillities:\nbool check(const Date &d);\ninline bool\nisLeapYear(Date::Size y);\n\n\n\n\n// check if the date object passed in is valid\n inline bool\n check(const Date &d)\n {\n     if(d.month==0 || d.month >12)\n         return false;\n     else\n     {\n         //    month == 1 3 5 7 8 10 12\n         if(d.month==1 || d.month==3 || d.month==5 || d.month==7 ||\n            d.month==8 || d.month==10|| d.month==12)\n         {\n             if(d.day==0 || d.day > 31) return false;\n             else\n                return true;\n         }\n         else\n         {\n             //    month == 4 6 9 11\n             if(d.month==4 || d.month==6 || d.month==9 || d.month==11)\n             {\n                 if(d.day==0 || d.day > 30) return false;\n                 else\n                     return true;\n             }\n             else\n             {\n                 //    month == 2\n                 if(isLeapYear(d.year))\n                 {\n                     if(d.day==0 || d.day >29)  return false;\n                     else\n                         return true;\n                 }\n                 else\n                 {\n                     if(d.day==0 || d.day >28)  return false;\n                     else\n                         return true;\n                 }\n             }\n         }\n     }\n }\n\n inline bool\n isLeapYear(Date::Size y)\n {\n     if (!(y%400))\n     {\n         return true;\n     }\n     else\n     {\n         if(!(y%100))\n         {\n             return false;\n         }\n         else\n             return !(y%4);\n     }\n }\n#endif // DATE_H\n"
  },
  {
    "path": "ch14/ex14_49_TEST.cpp",
    "content": "#include \"ex14_49.h\"\n\nint main()\n{\n    Date date(12, 4, 2015);\n    if (static_cast<bool>(date))\n        std::cout << date << std::endl;\n}\n"
  },
  {
    "path": "ch15/README.md",
    "content": "# Chapter 15. Object-Oriented Programming\n\n## Exercise 15.1:\n> What is a virtual member?\n\nA virtual member in a base class expects its derived class define its own version. In particular base classes ordinarily should define a virtual destructor, even if it does no work.\n\n## Exercise 15.2:\n> How does the protected access specifier differ from private?\n\n* **private member**: base class itself and friend can access\n* **protected members**: base class itself, friend and derived classes can access\n\n## Exercise 15.3:\n> Define your own versions of the `Quote` class and the `print_total` function.\n\n[Quote](ex15.1.2.3/quote.h) | [main.cpp](ex15.1.2.3/main.cpp)\n\n## Exercise 15.4:\n> Which of the following declarations, if any, are incorrect? Explain why.\n\n> class Base { ... };\n\n> (a) class Derived : public Derived { ... };\n\n> (b) class Derived : private Base { ... };\n\n> (c) class Derived : public Base;\n\n * (a): **incorrect**, derive from itself.\n * (b): **incorrect**, this is a definition not a declaration.\n * (c): **incorrect**, A derived class is declared like any other class. The declaration contains the class name but does not include its derivation list.\n\n## Exercise 15.5:\n> Define your own version of the `Bulk_quote` class.\n\n[Bulk_quote](ex15.4.5.6/bulk_quote.h)\n\n## Exercise 15.6:\n> Test your `print_total` function from the exercises in § 15.2.1 (p. 595) by passing both `Quote` and `Bulk_quote` objects o that function.\n\n[main](ex15.4.5.6/main.cpp)\n\n## [Exercise 15.7](ex15.7/main.cpp)\n\n## Exercise 15.8\n> Define static type and dynamic type.\n\nThe static type of an expression is always known at compile time.\n\nThe dynamic type is the type of the object in memory that the variable or expression represents. The dynamic type may not be known until run time.\n\n## Exercise 15.9:\n> When is it possible for an expression’s static type to differ from its dynamic type? Give three examples in which the static and dynamic type differ.\n\nThe static type of a pointer or reference to a base class may differ from its dynamic type. Anything like this can be an example.\n[Exercise 15.9](ex15.9/main.cpp)\n\n## Exercise 15.10:\n> Recalling the discussion from §8.1 (p. 311), explain how the program on page 317 that passed an `ifstream` to the `Sales_data` read function works.\n\nThe function takes a `std::istream` from which `std::ifstream` is derived. Hence the `ifstream` object \"is a\" i`stream` , which is why it works.\n\n## Exercise 15.11:\n> Add a virtual debug function to your `Quote` class hierarchy that displays the data members of the respective classes.\n\n```cpp\nvoid Quote::debug() const\n{\n    std::cout << \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \";\n}\n```\n[test](ex15.11/main.cpp)\n\n## Exercise 15.12:\n> Is it ever useful to declare a member function as both override and final? Why or why not?\n\n Sure. override means overriding the same name virtual function in base class. final means preventing any overriding this virtual function by any derived classes that are more lower at the hierarchy.\n\n## [Exercise 15.13](ex15.12.13.14/main.cpp)\n\n## [Exercise 15.14](ex15.12.13.14/main.cpp)\n\n## Exercise 15.15:\n> Define your own versions of `Disc_quote` and `Bulk_quote`.\n\n[Disc_quote](ex15.15.16.17/disc_quote.h) | [Bulk_quote](ex15.15.16.17/bulk_quote.h)\n\n## Exercise 15.16:\n> Rewrite the class representing a limited discount strategy, which you wrote for the exercises in § 15.2.2 (p. 601), to inherit from Disc_quote.\n\n[Limit_quote](ex15.15.16.17/limit_quote.h)\n\n## Exercise 15.17:\n> Try to define an object of type Disc_quote and see what errors you get from the compiler.\n\n`error: cannot declare variable 'd' to be of abstract type 'Disc_quote': Disc_quote d;`\n\n`note: because the following virtual functions are pure within 'Disc_quote':  class Disc_quote : public Quote`\n\n\n`note: virtual double Disc_quote::net_price(std::size_t) const: virtual double net_price(std::size_t n) const override = 0;`\n\n## Exercise 15.18:\n> Given the classes from page 612 and page 613, and assuming each object has the type specified in the comments, determine which of these assignments are legal. Explain why those that are illegal aren’t allowed:\n\n> Base \\*p = &d1;  //  d1 has type Pub_Derv\n\n> p = &d2;          //  d2 has type Priv_Derv\n\n> p = &d3;        //  d3 has type Prot_Derv\n\n> p = &dd1;       //  dd1 has type Derived_from_Public\n\n> p = &dd2;       //  dd2 has type Derived_from_Private\n\n> p = &dd3;       //  dd3 has type Derived_from_Protected\n\n* Base \\*p = &d1; **legal**\n* p = &d2; **illegal**\n* p = &d3; **illegal**\n* p = &dd1; **legal**\n* p = &dd2; **illegal**\n* p = &dd3; **illegal**\n\nUser code may use the derived-to-base conversion only if D inherits publicly from B. User code may not use the conversion if D inherits from B using either protected or private.\n\n## Exercise 15.19:\n> Assume that each of the classes from page 612 and page 613 has a member function of the form:\n\n> `void memfcn(Base &b) { b = *this; }`\n\n> For each class, determine whether this function would be legal.\n\nMember functions and friends of D can use the conversion to B regardless of how D inherits from B. The derived-to-base conversion to a direct base class is always accessible to members and friends of a derived class.\n\nHence, the 3 below are all legal:\n\n* Pub_Derv\n* Priv_Derv\n* Prot_Derv\n\nMember functions and friends of classes derived from D may use the derived-to-base conversion if D inherits from B using either public or protected. Such code may not use the conversion if D inherits privately from B.Hence:\n\n* Derived_from_Public **legal**\n* Derived_from_Private **illegal**\n* Derived_from_Protected **legal**\n\n## [Exercise 15.20](ex15.18.19.20/main.cpp)\n> Choose one of the following general abstractions containing a family of types (or choose one of your own). Organize the types into an inheritance hierarchy:\n\n> (a) Graphical file formats (such as gif, tiff, jpeg, bmp)\n\n> (b) Geometric primitives (such as box, circle, sphere, cone)\n\n> (c) C++ language types (such as class, function, member function)\n\n[Here is a example of 2D shape](ex15.21.22/main.cpp)\n\n## [Exercise 15.21](ex15.21.22/main.cpp)\n\n## Exercise 15.23:\n> Assuming class D1 on page 620 had intended to override its inherited `fcn` function, how would you fix that class? Assuming you fixed the class so that `fcn` matched the definition in Base, how would the calls in that section be resolved?\n\nremove the parameter int.\n\n[main](ex15.23.cpp) | [Disscussion on SO](http://stackoverflow.com/questions/21320779/trying-to-understand-dynamic-binding-and-virtual-functions)\n\n## Exercise 15.24:\n> What kinds of classes need a virtual destructor? What operations must a virtual destructor perform?\n\nGenerally, a base class should define a virtual destructor.\n\nThe destructor needs to be virtual to allow objects in the inheritance hierarchy to be dynamically allocated and destroyed.\n\n## Exercise 15.25:\n> Why did we define a default constructor for Disc_quote? What effect, if any, would removing that constructor have on the behavior of Bulk_quote?\n\nWithout it, when building the statement below, the compiler would complain that:\n\n> note: 'Bulk_quote::Bulk_quote()' is implicitly deleted because the default definition would be ill-formed.\n\nThe reason is that a constructor taking 4 parameters has been defined, which prevented the compiler generate synthesized version default constructor.\n\nAs a result, the default constructor of any class derived from it has been defined as deleted. Thus the default constructor must be defined explicitly so that the derived classes can call it when executing its default constructor.\n\n## Exercise 15.26:\n> Define the `Quote` and `Bulk_quote` copy-control members to do the same job as the synthesized versions. Give them and the other constructors print statements that identify which function is running. Write programs using these classes and predict what objects will be created and destroyed.\n\n>Compare your predictions with the output and continue experimenting until your predictions are reliably correct.\n\n[Quote](ex15.26/quote.h) | [Bulk_quote](ex15.26/bulk_quote.h)\n\n## Exercise 15.27:\n> Redefine your `Bulk_quote` class to inherit its constructors.\n\n**rules:**\n\n1. only inherit from the direct base class.\n2. default, copy and move constructors can not inherit.\n3. any data members of its own are default initialized.\n4. the rest details are in the section section 15.7.4.\n\n[Bulk_quote](ex15.27/bulk_quote.h)\n\n## [Exercise 15.28](ex15.28.29/main.cpp)\n\n## Exercise 15.29:\n> Repeat your program, but this time store `shared_ptrs` to objects of type `Quote`. Explain any discrepancy in the sum generated by the this version and the previous program. If there is no discrepancy, explain why there isn’t one.\n\nSince the vector from the previous exercise holds objects, there's no polymorphism happened while calling the virtual function net_price. Essentially, the objects held in it are the Quote subjects of the Bulk_quote objects being pushed back, Thus, the virtual net_price functions called are Quote::net_price. As a result, no discount was applied. The outcome was 9090.\n\nThe objects held for this exercise are smart pointers to the Quote objects.In this case, polymorphism happened as expected.The actual virtual functions being called are Bulk_quote::net_price that ensure discount is applied.Thus, the outcome is 6363. It can be found that 30% discount has been applied to the price calculation.\n\n## Exercise 15.30:\n> Write your own version of the `Basket` class and use it to compute prices for the same transactions as you used in the previous exercises.\n\n[Basket h](ex15.30/basket.h) | [Basket cpp](ex15.30/basket.cpp) | [main](ex15.30/main.cpp)\n\n## Exercise 15.31:\n> Given that s1, s2, s3, and s4 are all strings, determine what objects are created in the following expressions:\n\n> (a) `Query(s1) | Query(s2) & ~ Query(s3);`\n\n> (b) `Query(s1) | (Query(s2) & ~ Query(s3));`\n\n> (c) `(Query(s1) & (Query(s2)) | (Query(s3) & Query(s4)));`\n\n* (a) `OrQuery, AndQuery, NotQuery, WordQuery`\n* (b) the same as the previous one\n* (c) `OrQuery, AndQuery, WordQuery`\n\n## Exercise 15.32:\n> What happens when an object of type Query is copied, moved, assigned, and destroyed?\n\n* **copy:**\nWhile being copied, the synthesized copy constructor is called. It copies the data member into the new object. Since in this case, the data member is a shared pointer, while copying, the corresponding shared pointer points to the same address and the use count from the both shared pointer becomes 2.\n\n* **move:**\nwhile being moved, the synthesized move constructor is called. It moves the data member into the new object. In this case, the shared pointer from the newly created object will point to the address to which the original shared pointer pointed.\nAfter the move operation, the use count of the shared pointer in the new object is 1, whereas the pointer from the original object becomes `nullptr`.\n\n* **copy assignment:**\nThe synthesized copy assignment will be called. The outcome of this operation is identical with the copy operation.\n\n* **move assignment:**\nThe synthesized move assignment will be called. The rest is the same as the move operation.\n\n* **destroy:**\nThe synthesized destructor will be called. It will call the destructor of `shared_ptr` which decrements the use count. If the count becomes zero, the destructor from shared_ptr will delete the resources it point to.\n\n## Exercise 15.33:\n> What about objects of type `Query_base`?\n\nManaged by the synthesized version. Since Query_base a abstract class, the object of this type is essentially a subobject of its derived class.\n\n## Exercise 15.34:\n> For the expression built in Figure 15.3 (p. 638):\n\n> (a) List the constructors executed in processing that expression.\n\n> (b) List the calls to rep that are made from `cout << q`.\n\n> (c) List the calls to `eval` made from `q.eval()`.\n\n\n* **a:** Query q = Query(\"fiery\") & Query(\"bird\") | Query(\"wind\");\n\n\n1. `Query::Query(const std::string& s)` where s == \"fiery\",\"bird\" and \"wind\"\n2. `WordQuery::WordQuery(const std::string& s)` where s == \"fiery\",\"bird\" and \"wind\"\n3. `AndQuery::AndQuery(const Query& left, const Query& right);`\n4. `BinaryQuery(const Query&l, const Query& r, std::string s);`\n5. `Query::Query(std::shared_ptr<Query_base> query)` 2times\n6. `OrQuery::OrQuery(const Query& left, const Query& right);`\n7. `BinaryQuery(const Query&l, const Query& r, std::string s);`\n8. `Query::Query(std::shared_ptr<Query_base> query)` 2times\n\n\n* **b:**\n\n\n1. `query.rep()` inside the operator <<().\n2. `q->rep()` inside the member function rep().\n3. `OrQuery::rep()` which is inherited from `BinaryQuery`.\n4. `Query::rep()` for `lhs` and `rhs`:\nfor `rhs` which is a `WordQuery` : `WordQuery::rep()` where `query_word(\"wind\")` is returned.For `lhs` which is an `AndQuery`.\n5. `AndQuery::rep()` which is inherited from `BinaryQuery`.\n6. `BinaryQuer::rep()`: for `rhs: WordQuery::rep()`   where query_word(\"fiery\") is returned. For `lhs: WordQuery::rep()` where query_word(\"bird\" ) is returned.\n\n\n* **c:**\n\n\n1. `q.eval()`\n2. `q->rep()`: where q is a pointer to `OrQuary`.\n3. `QueryResult eval(const TextQuery& )const override`: is called but this one has not been defined yet.\n\n## Exercise 15.35:\n> Implement the `Query` and `Query_base classes`, including a definition of rep but omitting the definition of `eval`.\n\n[Query](ex15.34.35.36.38/query.h) | [Query_base](ex15.34.35.36.38/query_base.h)\n\n## Exercise 15.36:\n> Put print statements in the constructors and rep members and run your code to check your answers to (a) and (b) from the first exercise.\n\n```cpp\nQuery q = Query(\"fiery\") & Query(\"bird\") | Query(\"wind\");\n\nWordQuery::WordQuery(wind)\nQuery::Query(const std::string& s) where s=wind\nWordQuery::WordQuery(bird)\nQuery::Query(const std::string& s) where s=bird\nWordQuery::WordQuery(fiery)\nQuery::Query(const std::string& s) where s=fiery\nBinaryQuery::BinaryQuery()  where s=&\nAndQuery::AndQuery()\nQuery::Query(std::shared_ptr<Query_base> query)\nBinaryQuery::BinaryQuery()  where s=|\nOrQuery::OrQuery\nQuery::Query(std::shared_ptr<Query_base> query)\nPress <RETURN> to close this window...\n```\n\n```cpp\nstd::cout << q <<std::endl;\n\nQuery::rep()\nBinaryQuery::rep()\nQuery::rep()\nWodQuery::rep()\nQuery::rep()\nBinaryQuery::rep()\nQuery::rep()\nWodQuery::rep()\nQuery::rep()\nWodQuery::rep()\n((fiery & bird) | wind)\nPress <RETURN> to close this window...\n```\n\n## Exercise 15.37:\n\n## Exercise 15.38:\n> Are the following declarations legal? If not, why not? If so, explain what the declarations mean.\n\n> BinaryQuery a = Query(\"fiery\") & Query(\"bird\");\n\n>AndQuery b = Query(\"fiery\") & Query(\"bird\");\n\n> OrQuery c = Query(\"fiery\") & Query(\"bird\");\n\n\n1. Illegal. Because `BinaryQuery` is an abstract class.\n2. Illegal. Because operator & returns a `Query` which can not convert to an `AndQuery` object.\n3. Illegal. Because operator & returns a `Query` which can not convert to an `OrQuery` object.\n\n## Exercise 15.39:\n> Implement the `Query` and `Query_base` classes. Test your application by evaluating and printing a query such as the one in Figure 15.3 (p. 638).\n\n[Query](ex15.39.40/query.h) | [Query_base](ex15.34.35.36.38/query_base.h) | [main](ex15.39.40/main.cpp)\n\n## Exercise 15.40:\n> In the `OrQuery` eval function what would happen if its `rhs` member returned an empty set? What if its `lhs` member did so? What if both `rhs` and `lhs` returned empty sets?\n\nNothing special will happen.  The codes as following:\n\n```cpp\nstd::shared_ptr<std::set<line_no>> ret_lines =\n       std::make_shared<std::set<line_no>>(left.begin(), left.end());\n```\n\nSince `std::make_shared` will allocate dynamically a new `std::set`, nothing will be added into this `std::set` if any set is empty.The codes in main function proves this.\n\n## Exercise 15.41:\n\n## Exercise 15.42:\n>  Design and implement one of the following enhancements:\n\n> **(a)** Print words only once per sentence rather than once per line.\n\n> **(b)** Introduce a history system in which the user can refer to a previous query by number, possibly adding to it or combining it with another.\n\n> **(c)** Allow the user to limit the results so that only matches in a given range of lines are displayed.\n\nHere are solutions for [(b)](ex15.42_b/main.cpp) and [(c)](ex15.42_c/main.cpp).\n"
  },
  {
    "path": "ch15/ex15.1.2.3/CppPrimer.pro",
    "content": "TEMPLATE = app\nCONFIG += console\nCONFIG -= app_bundle\nCONFIG -= qt\nCONFIG += c++11\n\n\nSOURCES += main.cpp \\\n    quote.cpp\n\nHEADERS += \\\n    quote.h\n\n"
  },
  {
    "path": "ch15/ex15.1.2.3/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       21  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.1:\n// What is a virtual member?\n//  A virtual member in a base class expects its derived class define its own version.\n//  In particular base classes ordinarily should define a virtual destructor, even if\n//  it does no work.\n//\n// Exercise 15.2:\n// How does the protected access specifier differ from private?\n//      private members     :   base class itself and friend can access\n//      protected members   :   base class itself, friend and derived classes can access\n// Exercise 15.3:\n// Define your own versions of the Quote class and the print_total function.\n//\n//\n#include <iostream>\n#include <string>\n#include <map>\n#include <functional>\n\n#include \"quote.h\"\n\ndouble print_total (std::ostream& os, const Quote& item, size_t n);\n\nint main()\n{\n\n\n    return 0;\n}\n\n\ndouble print_total(std::ostream &os, const Quote &item, size_t n)\n{\n    double ret = item.net_price(n);\n\n    os << \"ISBN:\" << item.isbn()\n       << \"# sold: \" << n << \" total due: \" << ret << std::endl;\n\n    return ret;\n}\n"
  },
  {
    "path": "ch15/ex15.1.2.3/quote.cpp",
    "content": "#include \"quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.1.2.3/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n\nclass Quote\n{\npublic:\n    Quote() = default;\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n\n    virtual ~Quote() = default;\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 0.0;\n\n};\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.11/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= min_qty ? 1 - discount : 1);\n}\n\nvoid Bulk_quote::debug() const\n{\n\tQuote::debug();\n    std::cout << \"min_qty= \" << this->min_qty << \" \"\n              << \"discount= \" << this->discount<< \" \";\n}\n"
  },
  {
    "path": "ch15/ex15.11/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include \"quote.h\"\n\nclass Bulk_quote : public Quote\n{\npublic:\n    Bulk_quote() = default;\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Quote(b, p), min_qty(q), discount(disc)  {   }\n\n    double net_price(std::size_t n) const override;\n    void  debug() const override;\n\nprivate:\n    std::size_t min_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.11/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\n\nvoid Limit_quote::debug() const\n{\n\tQuote::debug();\n    std::cout << \"max_qty= \" << this->max_qty << \" \"\n              << \"discount= \" << this->discount<< \" \";\n}\n"
  },
  {
    "path": "ch15/ex15.11/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"quote.h\"\n\nclass Limit_quote : public Quote\n{\npublic:\n    Limit_quote();\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Quote(b, p), max_qty(max), discount(disc)    {   }\n\n    double net_price(std::size_t n) const override\n    { return n * price * (n < max_qty ? 1 - discount : 1 ); }\n\n    void debug() const override;\n\nprivate:\n    std::size_t max_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.11/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       22  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.11:\n// Add a virtual debug function to your Quote class hierarchy that displays\n// the data members of the respective classes.\n//\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n\nvoid print_debug(const Quote& q);\ndouble print_total (std::ostream& os, const Quote& item, size_t n);\nint main()\n{\n    Quote q(\"aaa\", 10.60);\n    Bulk_quote bq(\"bbb\", 111, 10, 0.3);\n    Limit_quote lq(\"ccc\", 222, 10, 0.3);\n\n    /** @note   Not dynamic binding!\n     *  The codes below are not dynamic binding. The compiler has known what the\n     *  r refering to at compile time. As a result, the virtual function debug of\n     *  the subobject is called.\n     */\n    Quote& r = q;\n    r.debug();\n\tstd::cout << \"\\n\";\n    r = bq;\n    r.debug();\n\tstd::cout << \"\\n\";\n    r = lq;\n    r.debug();\n\tstd::cout << \"\\n\";\n\n\n    std::cout << \"====================\\n\";\n\n    /** @note   dynamic binding!\n     *  The below will happen dynamic binding. The reason might be that while  print_debug\n     *  compiling the compiler compile it independly from the rest codes. The compiler has\n     *  no idea what the paramter q refering to. Thus compiler will leave the decision to\n     *  run time. That is, dynamic binding.\n     *\n     *  Once dynamic binding happens, the corresponding vertual function in derived class will\n     *  be called rather than that of the subobject inside the derived object.\n     *\n     *  Anyway, the reference is essentially an address being passed.\n     *\n     */\n    print_debug(q);\n\tstd::cout << \"\\n\";\n    print_debug(lq);\n\tstd::cout << \"\\n\";\n    print_debug(bq);\n\tstd::cout << \"\\n\";\n\n    return 0;\n}\n\ndouble print_total(std::ostream &os, const Quote &item, size_t n)\n{\n    double ret = item.net_price(n);\n\n    os << \"ISBN:\" << item.isbn()\n       << \"# sold: \" << n << \" total due: \" << ret << std::endl;\n\n    return ret;\n}\n\n\nvoid print_debug(const Quote &q)\n{\n    q.debug();\n}\n"
  },
  {
    "path": "ch15/ex15.11/quote.cpp",
    "content": "#include \"quote.h\"\n\nvoid Quote::debug() const\n{\n    std::cout << \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \";\n}\n"
  },
  {
    "path": "ch15/ex15.11/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\npublic:\n    Quote() = default;\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n    virtual void    debug() const;\n\n    virtual ~Quote() = default;\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 0.0;\n\n};\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.12.13.14/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= min_qty ? 1 - discount : 1);\n}\n\nvoid Bulk_quote::debug() const\n{\n    std::cout << \"data members of this class:\\n\"\n              << \"min_qty= \" << this->min_qty << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.12.13.14/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include “quote.h”\n\nclass Bulk_quote : public Quote\n{\npublic:\n    Bulk_quote() = default;\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Quote(b, p), min_qty(q), discount(disc)  {   }\n\n    double net_price(std::size_t n) const override;\n    void  debug() const override;\n\nprivate:\n    std::size_t min_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.12.13.14/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\n\nvoid Limit_quote::debug() const\n{\n    std::cout << \"data members of this class:\\n\"\n              << \"max_qty= \" << this->max_qty << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.12.13.14/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"quote.h\"\n\nclass Limit_quote : public Quote\n{\npublic:\n    Limit_quote();\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Quote(b, p), max_qty(max), discount(disc)    {   }\n\n    double net_price(std::size_t n) const override\n    { return n * price * (n < max_qty ? 1 - discount : 1 ); }\n\n    void debug() const override;\n\nprivate:\n    std::size_t max_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.12.13.14/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       22  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.12:\n// Is it ever useful to declare a member function as both override and final?\n// Why or why not?\n//  Sure. override means overriding the same name virtual function in base class.\n//  final means preventing any overriding this virtual function by any derived classes\n//  that are more lower at the hierarchy .\n//\n// Exercise 15.13:\n// Given the following classes, explain each print function:\n// If there is a problem in this code, how would you fix it?\n//\n// Exercise 15.14:\n// Given the classes from the previous exercise and the following objects,\n// determine which function is called at run time:\n//\n\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n\n\nclass base\n{\npublic:\n   std::string name() { return basename; }\n   virtual void print(std::ostream &os) { os << basename; }\n   //     ~~~~~^^^^^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n   //  The print here just output the basename of the base.\nprivate:\n   std::string basename = \"base\\n\";\n};\n\nclass derived : public base\n{\npublic:\n   void print(std::ostream &os) override { base::print(os); os << \" derived\\n \" << i; }\n   //   ^^^^^                   ^^^^^^^^   ^^^^^^    --  added to fix this problem\n   //  this print wanted to call the print from the base class.\n   //  however, the class scope base:: was omitted.As a result\n   //  it will cause an infinit recursion.\n   //  btw, we can add a keyword `override` to show this function\n   //  overrides a virtual function from the base class, although\n   //  it is not neccessary, but for security, the more, the better.\n\n\nprivate:\n   int i;\n};\n\n\nvoid print_debug(const Quote& q);\ndouble print_total (std::ostream& os, const Quote& item, size_t n);\nint main()\n{\n    // ex15.14\n    base bobj;\n    base *bp1 = &bobj;\n    base &br1 = bobj;\n    derived dobj;\n    base *bp2 = &dobj;\n    base &br2 = dobj;\n\n    // a.  this is an object, so compile time.\n    //bobj.print(std::cout);\n\n    // b.  this is an object, so compile time.\n    //dobj.print(std::cout);\n\n    // c.  function name is not virtual , so no dynamic\n    //     binding happens.so compile time\n    //std::cout << bp1->name();\n\n    // d.  function name is not virtual , so no dynamic\n    //     binding happens.so compile time\n    //std::cout << bp2->name();\n\n    // e.  run time\n    //br1.print(std::cout);\n\n    // f.  run time\n    br2.print(std::cout);\n\n\n    return 0;\n}\n\ndouble print_total(std::ostream &os, const Quote &item, size_t n)\n{\n    double ret = item.net_price(n);\n\n    os << \"ISBN:\" << item.isbn()\n       << \"# sold: \" << n << \" total due: \" << ret << std::endl;\n\n    return ret;\n}\n\n\nvoid print_debug(const Quote &q)\n{\n    q.debug();\n}\n"
  },
  {
    "path": "ch15/ex15.12.13.14/quote.cpp",
    "content": "#include \"quote.h\"\n\nvoid Quote::debug() const\n{\n    std::cout << \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.12.13.14/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\npublic:\n    Quote() = default;\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n    virtual void    debug() const;\n\n    virtual ~Quote() = default;\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 0.0;\n\n};\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.15.16.17/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= quantity ? 1 - discount : 1);\n}\n\nvoid Bulk_quote::debug() const\n{\n\tQuote::debug();\n    std::cout //<< \"data members of this class:\\n\"\n              << \"min_qty= \" << quantity << \" \"\n              << \"discount= \" << discount<< \" \";\n}\n"
  },
  {
    "path": "ch15/ex15.15.16.17/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include \"disc_quote.h\"\n\nclass Bulk_quote : public Disc_quote\n{\npublic:\n    Bulk_quote() = default;\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Disc_quote(b, p, q, disc) {   }\n\n    double net_price(std::size_t n) const override;\n    void  debug() const override;\n};\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.15.16.17/disc_quote.cpp",
    "content": "#include \"disc_quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.15.16.17/disc_quote.h",
    "content": "#ifndef DISC_QUOTE_H\n#define DISC_QUOTE_H\n\n#include \"quote.h\"\nclass Disc_quote : public Quote\n{\npublic:\n    Disc_quote();\n    Disc_quote(const std::string& b, double p, std::size_t q, double d) :\n        Quote(b, p), quantity(q), discount(d)   { }\n\n    virtual double net_price(std::size_t n) const override = 0;\n\nprotected:\n    std::size_t quantity;\n    double      discount;\n};\n\n#endif // DISC_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.15.16.17/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\n\nvoid Limit_quote::debug() const\n{\n\tQuote::debug();\n    std::cout //<< \"data members of this class:\\n\"\n              << \"max_qty= \" << quantity << \" \"\n              << \"discount= \" << discount<< \" \";\n}\n"
  },
  {
    "path": "ch15/ex15.15.16.17/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"disc_quote.h\"\n\nclass Limit_quote : public Disc_quote\n{\npublic:\n    Limit_quote() = default;\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Disc_quote(b, p, max, disc)  {   }\n\n    double net_price(std::size_t n) const override\n    { return n * price * (n < quantity ? 1 - discount : 1 ); }\n\n    void debug() const override;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.15.16.17/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       23  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.15:\n// Define your own versions of Disc_quote and Bulk_quote.\n//\n// Exercise 15.16:\n// Rewrite the class representing a limited discount strategy, which you wrote\n// for the exercises in § 15.2.2 (p. 601), to inherit from Disc_quote.\n//\n// Exercise 15.17:\n// Try to define an object of type Disc_quote and see what errors you get from\n// the compiler.\n//  error: cannot declare variable 'd' to be of abstract type 'Disc_quote'\n//           Disc_quote d;\n//                      ^\n//  note:  because the following virtual functions are pure within 'Disc_quote':\n//  class Disc_quote : public Quote\n//        ^\n//  note: \tvirtual double Disc_quote::net_price(std::size_t) const\n//  virtual double net_price(std::size_t n) const override = 0;\n//                 ^\n\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n#include \"disc_quote.h\"\n\n\n\nint main()\n{\n\t/*\n\terror C2259 : 'Disc_quote' : cannot instantiate abstract class\n\t1>          due to following members :\n\t1>          'double Disc_quote::net_price(size_t) const' : is abstract\n\t*/\n    Disc_quote d;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.15.16.17/quote.cpp",
    "content": "#include \"quote.h\"\n\nvoid Quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \";\n}\n"
  },
  {
    "path": "ch15/ex15.15.16.17/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\npublic:\n    Quote() = default;\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n    virtual void    debug() const;\n\n    virtual ~Quote() = default;\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 0.0;\n\n};\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.18.19.20/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       23  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.18:\n// Given the classes from page 612 and page 613, and assuming each object\n// has the type specified in the comments, determine which of these assignments\n// are legal. Explain why those that are illegal aren’t allowed:\n//\n//     Base *p = &d1;  //  d1 has type Pub_Derv    --  legal   --right\n//     p = &d2;        //  d2 has type Priv_Derv   --  illegal --right\n//     p = &d3;        //  d3 has type Prot_Derv   --  illegal --right\n//\n//     p = &dd1;       //  dd1 has type Derived_from_Public    --  legal   --right\n//     p = &dd2;       //  dd2 has type Derived_from_Private   --  illegal --right\n//     p = &dd3;       //  dd3 has type Derived_from_Protected --  illegal --right\n//\n//      User code may use the derived-to-base conversion only if D inherits\n//      publicly from B. User code may not use the conversion if D inherits\n//      from B using either protected or private.\n//\n// Exercise 15.19:\n// Assume that each of the classes from page 612 and page 613 has a member\n// function of the form:\n//\n//          void memfcn(Base &b) { b = *this; }\n//\n// For each class, determine whether this function would be legal.\n//\n//  Member functions and friends of D can use the conversion to B regardless\n//  of how D inherits from B. The derived-to-base conversion to a direct base\n//  class is always accessible to members and friends of a derived class.\n//  Hence, the 3 below are all legal:\n//\n//          Pub_Derv    --  legal   --right\n//          Priv_Derv   --  legal   --right\n//          Prot_Derv   --  legal   --right\n//\n//  Member functions and friends of classes derived from D may use the\n//  derived-to-base conversion if D inherits from B using either public or\n//  protected. Such code may not use the conversion if D inherits privately\n//  from B.Hence:\n//          Derived_from_Public    --  legal    --right\n//          Derived_from_Private   --  illegal  --right\n//          Derived_from_Protected --  legal    --right\n//\n// Exercise 15.20:\n// Write code to test your answers to the previous two exercises.\n//\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n#include \"disc_quote.h\"\n\nclass Base\n{\npublic:\n    void pub_mem();   // public member\nprotected:\n    int prot_mem;     // protected member\nprivate:\n    char priv_mem;    // private member\n};\n\nstruct Pub_Derv     : public    Base\n{\n    void memfcn(Base &b) { b = *this; }\n};\nstruct Priv_Derv    : private   Base\n{\n    void memfcn(Base &b) { b = *this; }\n};\nstruct Prot_Derv    : protected Base\n{\n    void memfcn(Base &b) { b = *this; }\n};\n\nstruct Derived_from_Public      : public Pub_Derv\n{\n    void memfcn(Base &b) { b = *this; }\n};\nstruct Derived_from_Private     : public Priv_Derv\n{\n    //void memfcn(Base &b) { b = *this; }\n};\nstruct Derived_from_Protected   : public Prot_Derv\n{\n    void memfcn(Base &b) { b = *this; }\n};\n\nint main()\n{\n    Pub_Derv d1;\n    Base *p = &d1;\n\n    Priv_Derv d2;\n    //p = &d2;\n\n    Prot_Derv d3;\n    //p = &d3;\n\n    Derived_from_Public dd1;\n    p = &dd1;\n\n    Derived_from_Private dd2;\n    //p =& dd2;\n\n    Derived_from_Protected dd3;\n    //p = &dd3;\n\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.21.22/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       23  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.21:\n// Choose one of the following general abstractions containing a family of\n// types (or choose one of your own). Organize the types into an inheritance\n// hierarchy:\n//     (a) Graphical file formats (such as gif, tiff, jpeg, bmp)\n//     (b) Geometric primitives (such as box, circle, sphere, cone)\n//     (c) C++ language types (such as class, function, member function)\n//\n// Exercise 15.22:\n// For the class you chose in the previous exercise, identify some of the\n// likely virtual functions as well as public and protected members.\n//\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n#include \"disc_quote.h\"\n\n// just for 2D shape\nclass Shape\n{\npublic:\n    typedef std::pair<double, double>    Coordinate;\n\n    Shape() = default;\n    Shape(const std::string& n) :\n        name(n) { }\n\n    virtual double area()       const = 0;\n    virtual double perimeter()  const = 0;\n\n    virtual ~Shape() = default;\nprivate:\n    std::string name;\n};\n\nclass Rectangle : public Shape\n{\npublic:\n    Rectangle() = default;\n    Rectangle(const std::string& n,\n              const Coordinate& a,\n              const Coordinate& b,\n              const Coordinate& c,\n              const Coordinate& d) :\n        Shape(n), a(a), b(b), c(c), d(d) { }\n\n    ~Rectangle() = default;\n\nprotected:\n    Coordinate  a;\n    Coordinate  b;\n    Coordinate  c;\n    Coordinate  d;\n};\n\nclass Square : public Rectangle\n{\npublic:\n    Square() = default;\n    Square(const std::string& n,\n           const Coordinate& a,\n           const Coordinate& b,\n           const Coordinate& c,\n           const Coordinate& d) :\n        Rectangle(n, a, b, c, d) { }\n\n    ~Square() = default;\n};\n\n\nint main()\n{\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.23.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       24  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.23:\n// Assuming class D1 on page 620 had intended to override its inherited fcn\n// function, how would you fix that class? Assuming you fixed the class so\n// that fcn matched the definition in Base, how would the calls in that section\n// be resolved?\n//  remove the parameter int.\n//  Disscussion on SO :\n//  http://stackoverflow.com/questions/21320779/trying-to-understand-dynamic-binding-and-virtual-functions\n\n#include <iostream>\n#include <string>\n\nclass Base\n{\npublic:\n    virtual int fcn(){ std::cout << \"Base::fcn()\\n\"; return 0; }\n};\n\nclass D1 : public Base\n{\npublic:\n    int fcn() override  { std::cout << \"D1::fcn()\\n\";return 0; }\n    // ^^^--fixed to override the inherited version\n    virtual void f2() { std::cout << \"D1::f2()\\n\"; }\n};\n\nclass D2 : public D1\n{\npublic:\n    int fcn(int);\n    int fcn() override { std::cout << \"D2::fcn()\\n\";return 0; }\n    void f2() override { std::cout << \"D2::f2()\\n\"; }\n};\n\nint main()\n{\n    Base bobj;\n    D1 d1obj;\n    D2 d2obj;\n\n    Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;\n    //bp1->fcn(); // virtual call, will call Base::fcn at run time\n    //bp2->fcn(); // virtual call, will call D1::fcn   at run time\n    //bp3->fcn(); // virtual call, will call D2::fcn   at run time\n\n    D1 *d1p = &d1obj; D2 *d2p = &d2obj;\n\n    //bp2->f2();\n //^^^^^^^^^^^^\n    // @note   You are calling virtual member functions via a pointer\n    // to Base. That means that you can only call methods that exist\n    // in the Base class. You cannot simply add methods to a type\n    // dynamically.\n    //d1p->f2();    // virtual call, will call D1::f2() at run time\n    //d2p->f2();    // virtual call, will call D2::f2() at run time\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.24.25.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       24  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.24:\n// What kinds of classes need a virtual destructor? What operations must a\n// virtual destructor perform?\n//  Generally, a base class should define a virtual destructor.\n//  The destructor needs to be virtual to allow objects in the inheritance\n//  hierarchy to be dynamically allocated and destroyed.\n//\n// Exercise 15.25:\n// Why did we define a default constructor for Disc_quote? What effect, if\n// any, would removing that constructor have on the behavior of Bulk_quote?\n//\n//  Without it, when building the statement below, the compiler would complain\n//  that:\n//\n// note: 'Bulk_quote::Bulk_quote()' is implicitly deleted because the default\n// definition would be ill-formed.\n//\n//  The reason is that a constructor taking 4 parameters has been defined, which\n//  prevented the compiler generate synthesized version default constructor. As a\n//  result, the default constructor of any class derived from it has been defined\n//  as deleted. Thus the default constructor must be defined explicitly so that\n//  the derived classes can call it when executing its default constructor.\n//\n\nint main(){ return 0; }\n"
  },
  {
    "path": "ch15/ex15.26/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= quantity ? 1 - discount : 1);\n}\n\nvoid Bulk_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"min_qty= \" << quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.26/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include \"disc_quote.h\"\n\nclass Bulk_quote : public Disc_quote\n{\n\npublic:\n    Bulk_quote() { std::cout << \"default constructing Bulk_quote\\n\"; }\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Disc_quote(b, p, q, disc) { std::cout << \"Bulk_quote : constructor taking 4 parameters\\n\"; }\n\n    // copy constructor\n    Bulk_quote(const Bulk_quote& bq) : Disc_quote(bq)\n    { std::cout << \"Bulk_quote : copy constructor\\n\"; }\n\n    // move constructor\n    //page 535, \" In a constructor, noexcept appears between the parameter list and the : that begins the constructor initializer list\"\n    Bulk_quote(Bulk_quote&& bq) noexcept : Disc_quote(std::move(bq))\n    {\n        std::cout << \"Bulk_quote : move constructor\\n\";\n    }\n\n    // copy =()\n    Bulk_quote& operator =(const Bulk_quote& rhs)\n    {\n        Disc_quote::operator =(rhs);\n        std::cout << \"Bulk_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n\n    // move =()\n    Bulk_quote& operator =(Bulk_quote&& rhs) noexcept\n    {\n        Disc_quote::operator =(std::move(rhs));\n        std::cout << \"Bulk_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    double net_price(std::size_t n) const override;\n    void  debug() const override;\n\n    ~Bulk_quote() override\n    {\n        std::cout << \"destructing Bulk_quote\\n\";\n    }\n};\n\n\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.26/disc_quote.cpp",
    "content": "#include \"disc_quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.26/disc_quote.h",
    "content": "#ifndef DISC_QUOTE_H\n#define DISC_QUOTE_H\n\n#include \"quote.h\"\nclass Disc_quote : public Quote\n{\n    friend bool operator !=(const Disc_quote& lhs, const Disc_quote& rhs);\npublic:\n    Disc_quote() { std::cout << \"default constructing Disc_quote\\n\"; }\n\n    Disc_quote(const std::string& b, double p, std::size_t q, double d) :\n        Quote(b, p), quantity(q), discount(d)\n    {\n        std::cout << \"Disc_quote : constructor taking 4 parameters.\\n\";\n    }\n\n    // copy constructor\n    Disc_quote(const Disc_quote& dq) :\n        Quote(dq), quantity(dq.quantity), discount(dq.discount)\n    {\n        std::cout << \"Disc_quote : copy constructor.\\n\";\n    }\n\n    // move constructor\n    Disc_quote(Disc_quote&& dq) noexcept :\n        Quote(std::move(dq)), quantity(std::move(dq.quantity)), discount(std::move(dq.discount))\n    {\n        std::cout << \"Disc_quote : move constructor.\\n\";\n    }\n\n    // copy =()\n    Disc_quote& operator =(const Disc_quote& rhs)\n    {\n        Quote::operator =(rhs);\n        this->quantity = rhs.quantity;\n        this->discount = rhs.discount;\n\n        std::cout << \"Disc_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n    // move =()\n    Disc_quote& operator =(Disc_quote&& rhs) noexcept\n    {\n        if (*this != rhs)\n        {\n            Quote::operator =(std::move(rhs));\n            this->quantity = std::move(rhs.quantity);\n            this->discount = std::move(rhs.discount);\n        }\n        std::cout << \"Disc_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    virtual double net_price(std::size_t n) const override = 0;\n\n    ~Disc_quote()\n    {\n        std::cout << \"destructing Dis_quote\\n\";\n    }\n\nprotected:\n    std::size_t quantity = 3;\n    double      discount = 0.0;\n};\n\nbool inline\noperator !=(const Disc_quote& lhs, const Disc_quote& rhs)\n{\n    return Quote(lhs) != Quote(rhs)\n            &&\n            lhs.quantity != rhs.quantity\n            &&\n            lhs.discount != rhs.discount;\n}\n\n#endif // DISC_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.26/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\n\nvoid Limit_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"max_qty= \" << this->quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.26/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"disc_quote.h\"\n\nclass Limit_quote : public Disc_quote\n{\npublic:\n    Limit_quote() = default;\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Disc_quote(b, p, max, disc)  {   }\n\n    double net_price(std::size_t n) const override\n    { return n * price * (n < quantity ? 1 - discount : 1 ); }\n\n    void debug() const override;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.26/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       27  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.26:\n// Define the Quote and Bulk_quote copy-control members to do the same job\n// as the synthesized versions. Give them and the other constructors print\n// statements that identify which function is running. Write programs using\n// these classes and predict what objects will be created and destroyed.\n// Compare your predictions with the output and continue experimenting\n// until your predictions are reliably correct.\n//\n\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n#include \"disc_quote.h\"\n\n\nint main()\n{\n    Bulk_quote bq1;\n    Bulk_quote bq2(\"ss\", 2.05, 12, 0.3);\n    bq2 = std::move(bq2);\n\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.26/quote.cpp",
    "content": "#include \"quote.h\"\n\nvoid Quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.26/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\n    friend bool operator !=(const Quote& lhs, const Quote& rhs);\npublic:\n    Quote() { std::cout << \"default constructing Quote\\n\"; }\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { std::cout << \"Quote : constructor taking 2 parameters\\n\"; }\n\n    // copy constructor\n    Quote(const Quote& q) : bookNo(q.bookNo), price(q.price)\n    { std::cout << \"Quote: copy constructing\\n\"; }\n\n    // move constructor\n    Quote(Quote&& q) noexcept : bookNo(std::move(q.bookNo)), price(std::move(q.price))\n    { std::cout << \"Quote: move constructing\\n\"; }\n\n    // copy =\n    Quote& operator =(const Quote& rhs)\n    {\n        if(*this != rhs)\n        {\n            bookNo = rhs.bookNo;\n            price  = rhs.price;\n        }\n        std::cout << \"Quote: copy =() \\n\";\n\n        return *this;\n    }\n\n    // move =\n    Quote& operator =(Quote&& rhs)  noexcept\n    {\n        if(*this != rhs)\n        {\n            bookNo = std::move(rhs.bookNo);\n            price  = std::move(rhs.price);\n        }\n        std::cout << \"Quote: move =!!!!!!!!! \\n\";\n\n        return *this;\n    }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n    virtual void    debug() const;\n\n    virtual ~Quote()\n    {\n        std::cout << \"destructing Quote\\n\";\n    }\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 10.0;\n};\n\nbool inline\noperator !=(const Quote& lhs, const Quote& rhs)\n{\n    return lhs.bookNo != rhs.bookNo\n           &&\n           lhs.price  != rhs.price;\n}\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.27/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= quantity ? 1 - discount : 1);\n}\n\nvoid Bulk_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"min_qty= \" << quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.27/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include \"disc_quote.h\"\n\nclass Bulk_quote : public Disc_quote\n{\n\npublic:\n    Bulk_quote() { std::cout << \"default constructing Bulk_quote\\n\"; }\n\n    // changed the below to the inherited constructor for ex15.27.\n    // rules:  1. only inherit from the direct base class.\n    //         2. default, copy and move constructors can not inherit.\n    //         3. any data members of its own are default initialized.\n    //         4. the rest details are in the section section 15.7.4.\n    /*\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Disc_quote(b, p, q, disc) { std::cout << \"Bulk_quote : constructor taking 4 parameters\\n\"; }\n    */\n    using Disc_quote::Disc_quote;\n\n    // copy constructor\n    Bulk_quote(const Bulk_quote& bq) : Disc_quote(bq)\n    { std::cout << \"Bulk_quote : copy constructor\\n\"; }\n\n    // move constructor\n    Bulk_quote(Bulk_quote&& bq) : Disc_quote(std::move(bq))\n    {\n        std::cout << \"Bulk_quote : move constructor\\n\";\n    }\n\n    // copy =()\n    Bulk_quote& operator =(const Bulk_quote& rhs)\n    {\n        Disc_quote::operator =(rhs);\n        std::cout << \"Bulk_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n\n    // move =()\n    Bulk_quote& operator =(Bulk_quote&& rhs)\n    {\n        Disc_quote::operator =(std::move(rhs));\n        std::cout << \"Bulk_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    double net_price(std::size_t n) const override;\n    void  debug() const override;\n\n    ~Bulk_quote() override\n    {\n        std::cout << \"destructing Bulk_quote\\n\";\n    }\n};\n\n\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.27/disc_quote.cpp",
    "content": "#include \"disc_quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.27/disc_quote.h",
    "content": "#ifndef DISC_QUOTE_H\n#define DISC_QUOTE_H\n\n#include \"quote.h\"\nclass Disc_quote : public Quote\n{\n    friend bool operator !=(const Disc_quote& lhs, const Disc_quote& rhs);\npublic:\n    Disc_quote() { std::cout << \"default constructing Disc_quote\\n\"; }\n\n    Disc_quote(const std::string& b, double p, std::size_t q, double d) :\n        Quote(b, p), quantity(q), discount(d)\n    {\n        std::cout << \"Disc_quote : constructor taking 4 parameters.\\n\";\n    }\n\n    // copy constructor\n    Disc_quote(const Disc_quote& dq) :\n        Quote(dq), quantity(dq.quantity), discount(dq.discount)\n    {\n        std::cout << \"Disc_quote : copy constructor.\\n\";\n    }\n\n    // move constructor\n    Disc_quote(Disc_quote&& dq) noexcept :\n        Quote(std::move(dq)), quantity(std::move(dq.quantity)), discount(std::move(dq.discount))\n    {\n        std::cout << \"Disc_quote : move constructor.\\n\";\n    }\n\n    // copy =()\n    Disc_quote& operator =(const Disc_quote& rhs)\n    {\n        Quote::operator =(rhs);\n        this->quantity = rhs.quantity;\n        this->discount = rhs.discount;\n\n        std::cout << \"Disc_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n    // move =()\n    Disc_quote& operator =(Disc_quote&& rhs) noexcept\n    {\n        if (*this != rhs)\n        {\n            Quote::operator =(std::move(rhs));\n            this->quantity = std::move(rhs.quantity);\n            this->discount = std::move(rhs.discount);\n        }\n        std::cout << \"Disc_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    virtual double net_price(std::size_t n) const override = 0;\n\n    ~Disc_quote()\n    {\n        std::cout << \"destructing Dis_quote\\n\";\n    }\n\nprotected:\n    std::size_t quantity = 3;\n    double      discount = 0.0;\n};\n\nbool inline\noperator !=(const Disc_quote& lhs, const Disc_quote& rhs)\n{\n    return Quote(lhs) != Quote(rhs)\n            &&\n            lhs.quantity != rhs.quantity\n            &&\n            lhs.discount != rhs.discount;\n}\n\n#endif // DISC_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.27/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\n\nvoid Limit_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"max_qty= \" << this->quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.27/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"disc_quote.h\"\n\nclass Limit_quote : public Disc_quote\n{\npublic:\n    Limit_quote() = default;\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Disc_quote(b, p, max, disc)  {   }\n\n    double net_price(std::size_t n) const override\n    { return n * price * (n < quantity ? 1 - discount : 1 ); }\n\n    void debug() const override;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.27/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       28  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.27:\n// Redefine your Bulk_quote class to inherit its constructors.\n//  rules:  1. only inherit from the direct base class.\n//          2. default, copy and move constructors can not inherit.\n//          3. any data members of its own are default initialized.\n//          4. the rest details are in the section section 15.7.4.\n//\n\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n#include \"disc_quote.h\"\n\n\nint main()\n{\n    Bulk_quote bq(\"sss\", 20.0, 2, 0.3);\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.27/quote.cpp",
    "content": "#include \"quote.h\"\n\nvoid Quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.27/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\n    friend bool operator !=(const Quote& lhs, const Quote& rhs);\npublic:\n    Quote() { std::cout << \"default constructing Quote\\n\"; }\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { std::cout << \"Quote : constructor taking 2 parameters\\n\"; }\n\n    // copy constructor\n    Quote(const Quote& q) : bookNo(q.bookNo), price(q.price)\n    { std::cout << \"Quote: copy constructing\\n\"; }\n\n    // move constructor\n    Quote(Quote&& q) noexcept : bookNo(std::move(q.bookNo)), price(std::move(q.price))\n    { std::cout << \"Quote: move constructing\\n\"; }\n\n    // copy =\n    Quote& operator =(const Quote& rhs)\n    {\n        if(*this != rhs)\n        {\n            bookNo = rhs.bookNo;\n            price  = rhs.price;\n        }\n        std::cout << \"Quote: copy =() \\n\";\n\n        return *this;\n    }\n\n    // move =\n    Quote& operator =(Quote&& rhs)  noexcept\n    {\n        if(*this != rhs)\n        {\n            bookNo = std::move(rhs.bookNo);\n            price  = std::move(rhs.price);\n        }\n        std::cout << \"Quote: move =!!!!!!!!! \\n\";\n\n        return *this;\n    }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n    virtual void    debug() const;\n\n    virtual ~Quote()\n    {\n        std::cout << \"destructing Quote\\n\";\n    }\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 10.0;\n};\n\nbool inline\noperator !=(const Quote& lhs, const Quote& rhs)\n{\n    return lhs.bookNo != rhs.bookNo\n           &&\n           lhs.price  != rhs.price;\n}\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.28.29/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= quantity ? 1 - discount : 1);\n}\n\nvoid Bulk_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"min_qty= \" << quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.28.29/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include \"disc_quote.h\"\n\nclass Bulk_quote : public Disc_quote\n{\n\npublic:\n    Bulk_quote() { std::cout << \"default constructing Bulk_quote\\n\"; }\n\n    // changed the below to the inherited constructor for ex15.27.\n    // rules:  1. only inherit from the direct base class.\n    //         2. default, copy and move constructors can not inherit.\n    //         3. any data members of its own are default initialized.\n    //         4. the rest details are in the section section 15.7.4.\n    /*\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Disc_quote(b, p, q, disc) { std::cout << \"Bulk_quote : constructor taking 4 parameters\\n\"; }\n    */\n    using Disc_quote::Disc_quote;\n\n    // copy constructor\n    Bulk_quote(const Bulk_quote& bq) : Disc_quote(bq)\n    { std::cout << \"Bulk_quote : copy constructor\\n\"; }\n\n    // move constructor\n    Bulk_quote(Bulk_quote&& bq) : Disc_quote(std::move(bq))\n    {\n        std::cout << \"Bulk_quote : move constructor\\n\";\n    }\n\n    // copy =()\n    Bulk_quote& operator =(const Bulk_quote& rhs)\n    {\n        Disc_quote::operator =(rhs);\n        std::cout << \"Bulk_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n\n    // move =()\n    Bulk_quote& operator =(Bulk_quote&& rhs)\n    {\n        Disc_quote::operator =(std::move(rhs));\n        std::cout << \"Bulk_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    double net_price(std::size_t n) const override;\n    void  debug() const override;\n\n    ~Bulk_quote() override\n    {\n        std::cout << \"destructing Bulk_quote\\n\";\n    }\n};\n\n\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.28.29/disc_quote.cpp",
    "content": "#include \"disc_quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.28.29/disc_quote.h",
    "content": "#ifndef DISC_QUOTE_H\n#define DISC_QUOTE_H\n\n#include \"quote.h\"\nclass Disc_quote : public Quote\n{\n    friend bool operator !=(const Disc_quote& lhs, const Disc_quote& rhs);\npublic:\n    Disc_quote() { std::cout << \"default constructing Disc_quote\\n\"; }\n\n    Disc_quote(const std::string& b, double p, std::size_t q, double d) :\n        Quote(b, p), quantity(q), discount(d)\n    {\n        std::cout << \"Disc_quote : constructor taking 4 parameters.\\n\";\n    }\n\n    // copy constructor\n    Disc_quote(const Disc_quote& dq) :\n        Quote(dq), quantity(dq.quantity), discount(dq.discount)\n    {\n        std::cout << \"Disc_quote : copy constructor.\\n\";\n    }\n\n    // move constructor\n    Disc_quote(Disc_quote&& dq) noexcept :\n        Quote(std::move(dq)), quantity(std::move(dq.quantity)), discount(std::move(dq.discount))\n    {\n        std::cout << \"Disc_quote : move constructor.\\n\";\n    }\n\n    // copy =()\n    Disc_quote& operator =(const Disc_quote& rhs)\n    {\n        Quote::operator =(rhs);\n        this->quantity = rhs.quantity;\n        this->discount = rhs.discount;\n\n        std::cout << \"Disc_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n    // move =()\n    Disc_quote& operator =(Disc_quote&& rhs) noexcept\n    {\n        if (*this != rhs)\n        {\n            Quote::operator =(std::move(rhs));\n            this->quantity = std::move(rhs.quantity);\n            this->discount = std::move(rhs.discount);\n        }\n        std::cout << \"Disc_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    virtual double net_price(std::size_t n) const override = 0;\n\n    ~Disc_quote()\n    {\n        std::cout << \"destructing Dis_quote\\n\";\n    }\n\nprotected:\n    std::size_t quantity = 3;\n    double      discount = 0.0;\n};\n\nbool inline\noperator !=(const Disc_quote& lhs, const Disc_quote& rhs)\n{\n    return Quote(lhs) != Quote(rhs)\n            &&\n            lhs.quantity != rhs.quantity\n            &&\n            lhs.discount != rhs.discount;\n}\n\n#endif // DISC_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.28.29/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\n\nvoid Limit_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"max_qty= \" << this->quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.28.29/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"disc_quote.h\"\n\nclass Limit_quote : public Disc_quote\n{\npublic:\n    Limit_quote() = default;\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Disc_quote(b, p, max, disc)  {   }\n\n    double net_price(std::size_t n) const override\n    { return n * price * (n < quantity ? 1 - discount : 1 ); }\n\n    void debug() const override;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.28.29/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       28  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n// Exercise 15.28:\n// Define a vector to hold Quote objects but put Bulk_quote objects into that\n// vector. Compute the total net_price of all the elements in the vector.\n//\n// Exercise 15.29:\n// Repeat your program, but this time store shared_ptrs to objects of type\n// Quote. Explain any discrepancy in the sum generated by the this version and\n// the previous program.\n//\n//  Since the vector from the previous exercise holds objects, there's no polymorphism\n//  happened while calling the virtual function net_price. Essentially, the objects\n//  held in it are the Quote subjects of the Bulk_quote objects being pushed back,\n//  Thus, the virtual net_price functions called are Quote::net_price. As a result,\n//  no discount was applied. The outcome was 9090\n//\n//  The objects held for this exercise are smart pointers to the Quote objects.In this\n//  case, polymorphism happened as expected.The actual virtual functions being called\n//  are Bulk_quote::net_price that ensure discount is applied.Thus, the outcome is 6363.\n//  It can be found that 30% discount has been applied to the price calculation.\n//\n//\n// If there is no discrepancy, explain why there isn’t one.\n//\n\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <memory>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n#include \"disc_quote.h\"\n\n\nint main()\n{\n    /**\n     * @brief ex15.28   outcome == 9090\n     */\n    std::vector<Quote> v;\n    for(unsigned i =1; i != 10; ++i)\n        v.push_back(Bulk_quote(\"sss\", i * 10.1, 10, 0.3));\n\n    double total = 0;\n    for (const auto& b : v)\n    {\n        total += b.net_price(20);\n    }\n    std::cout << total << std::endl;\n\n    std::cout << \"======================\\n\\n\";\n\n    /**\n     * @brief ex15.29   outccome == 6363\n     */\n    std::vector<std::shared_ptr<Quote>> pv;\n\n    for(unsigned i =1; i != 10; ++i)\n        pv.push_back(std::make_shared<Bulk_quote>(Bulk_quote(\"sss\", i * 10.1, 10, 0.3)));\n\n    double total_p = 0;\n    for (auto p : pv)\n    {\n        total_p +=  p->net_price(20);\n    }\n    std::cout << total_p << std::endl;\n\n    return 0;\n\n}\n"
  },
  {
    "path": "ch15/ex15.28.29/quote.cpp",
    "content": "#include \"quote.h\"\n\nvoid Quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.28.29/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\n    friend bool operator !=(const Quote& lhs, const Quote& rhs);\npublic:\n    Quote() { std::cout << \"default constructing Quote\\n\"; }\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { std::cout << \"Quote : constructor taking 2 parameters\\n\"; }\n\n    // copy constructor\n    Quote(const Quote& q) : bookNo(q.bookNo), price(q.price)\n    { std::cout << \"Quote: copy constructing\\n\"; }\n\n    // move constructor\n    Quote(Quote&& q) noexcept : bookNo(std::move(q.bookNo)), price(std::move(q.price))\n    { std::cout << \"Quote: move constructing\\n\"; }\n\n    // copy =\n    Quote& operator =(const Quote& rhs)\n    {\n        if(*this != rhs)\n        {\n            bookNo = rhs.bookNo;\n            price  = rhs.price;\n        }\n        std::cout << \"Quote: copy =() \\n\";\n\n        return *this;\n    }\n\n    // move =\n    Quote& operator =(Quote&& rhs)  noexcept\n    {\n        if(*this != rhs)\n        {\n            bookNo = std::move(rhs.bookNo);\n            price  = std::move(rhs.price);\n        }\n        std::cout << \"Quote: move =!!!!!!!!! \\n\";\n\n        return *this;\n    }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n    virtual void    debug() const;\n\n    virtual ~Quote()\n    {\n        std::cout << \"destructing Quote\\n\";\n    }\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 10.0;\n};\n\nbool inline\noperator !=(const Quote& lhs, const Quote& rhs)\n{\n    return lhs.bookNo != rhs.bookNo\n           &&\n           lhs.price  != rhs.price;\n}\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.30/basket.cpp",
    "content": "#include \"basket.h\"\ndouble Basket::total_receipt(std::ostream &os) const\n{\n    double sum = 0.0;\n\n    for(auto iter = items.cbegin(); iter != items.cend();\n        iter = items.upper_bound(*iter))\n        //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n        // @note   this increment moves iter to the first element with key\n        //         greater than  *iter.\n\n    {\n        sum += print_total(os, **iter, items.count(*iter));\n    }                                   // ^^^^^^^^^^^^^ using count to fetch\n                                        // the number of the same book.\n    os << \"Total Sale: \" << sum << std::endl;\n    return sum;\n}\n"
  },
  {
    "path": "ch15/ex15.30/basket.h",
    "content": "#ifndef BASKET_H\n#define BASKET_H\n\n#include \"quote.h\"\n#include <set>\n#include <memory>\n\n\n// a basket of objects from Quote hierachy, using smart pointers.\nclass Basket\n{\npublic:\n    // copy verison\n    void add_item(const Quote& sale)\n    { items.insert(std::shared_ptr<Quote>(sale.clone())); }\n    // move version\n    void add_item(Quote&& sale)\n    { items.insert(std::shared_ptr<Quote>(std::move(sale).clone())); }\n\n    double total_receipt(std::ostream& os) const;\n\nprivate:\n\n    // function to compare needed by the multiset member\n    static bool compare(const std::shared_ptr<Quote>& lhs,\n                        const std::shared_ptr<Quote>& rhs)\n    { return lhs->isbn() < rhs->isbn(); }\n\n    // hold multiple quotes, ordered by the compare member\n    std::multiset<std::shared_ptr<Quote>, decltype(compare)*>\n                items{ compare };\n};\n\n#endif // BASKET_H\n"
  },
  {
    "path": "ch15/ex15.30/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= quantity ? 1 - discount : 1);\n}\n\nvoid Bulk_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"min_qty= \" << quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.30/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include \"disc_quote.h\"\n\nclass Bulk_quote : public Disc_quote\n{\n\npublic:\n    Bulk_quote() { std::cout << \"default constructing Bulk_quote\\n\"; }\n\n    // changed the below to the inherited constructor for ex15.27.\n    // rules:  1. only inherit from the direct base class.\n    //         2. default, copy and move constructors can not inherit.\n    //         3. any data members of its own are default initialized.\n    //         4. the rest details are in the section section 15.7.4.\n    /*\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Disc_quote(b, p, q, disc) { std::cout << \"Bulk_quote : constructor taking 4 parameters\\n\"; }\n    */\n    using Disc_quote::Disc_quote;\n\n    // copy constructor\n    Bulk_quote(const Bulk_quote& bq) : Disc_quote(bq)\n    { std::cout << \"Bulk_quote : copy constructor\\n\"; }\n\n    // move constructor\n    Bulk_quote(Bulk_quote&& bq) : Disc_quote(std::move(bq))\n    {\n        std::cout << \"Bulk_quote : move constructor\\n\";\n    }\n\n    // copy =()\n    Bulk_quote& operator =(const Bulk_quote& rhs)\n    {\n        Disc_quote::operator =(rhs);\n        std::cout << \"Bulk_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n\n    // move =()\n    Bulk_quote& operator =(Bulk_quote&& rhs)\n    {\n        Disc_quote::operator =(std::move(rhs));\n        std::cout << \"Bulk_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    // clone self\n    virtual Bulk_quote* clone() const & { return new Bulk_quote(*this); }\n    virtual Bulk_quote* clone() &&      { return new Bulk_quote(std::move(*this)); }\n\n    double net_price(std::size_t n) const override;\n    void  debug() const override;\n\n    ~Bulk_quote() override\n    {\n        std::cout << \"destructing Bulk_quote\\n\";\n    }\n};\n\n\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.30/disc_quote.cpp",
    "content": "#include \"disc_quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.30/disc_quote.h",
    "content": "#ifndef DISC_QUOTE_H\n#define DISC_QUOTE_H\n\n#include \"quote.h\"\nclass Disc_quote : public Quote\n{\n    friend bool operator !=(const Disc_quote& lhs, const Disc_quote& rhs);\npublic:\n    Disc_quote() { std::cout << \"default constructing Disc_quote\\n\"; }\n\n    Disc_quote(const std::string& b, double p, std::size_t q, double d) :\n        Quote(b, p), quantity(q), discount(d)\n    {\n        std::cout << \"Disc_quote : constructor taking 4 parameters.\\n\";\n    }\n\n    // copy constructor\n    Disc_quote(const Disc_quote& dq) :\n        Quote(dq), quantity(dq.quantity), discount(dq.discount)\n    {\n        std::cout << \"Disc_quote : copy constructor.\\n\";\n    }\n\n    // move constructor\n    Disc_quote(Disc_quote&& dq) noexcept :\n        Quote(std::move(dq)), quantity(std::move(dq.quantity)), discount(std::move(dq.discount))\n    {\n        std::cout << \"Disc_quote : move constructor.\\n\";\n    }\n\n    // copy =()\n    Disc_quote& operator =(const Disc_quote& rhs)\n    {\n        Quote::operator =(rhs);\n        this->quantity = rhs.quantity;\n        this->discount = rhs.discount;\n\n        std::cout << \"Disc_quote : copy =()\\n\";\n\n        return *this;\n    }\n\n    // move =()\n    Disc_quote& operator =(Disc_quote&& rhs) noexcept\n    {\n        if (*this != rhs)\n        {\n            Quote::operator =(std::move(rhs));\n            this->quantity = std::move(rhs.quantity);\n            this->discount = std::move(rhs.discount);\n        }\n        std::cout << \"Disc_quote : move =()\\n\";\n\n        return *this;\n    }\n\n    virtual double net_price(std::size_t n) const override = 0;\n\n    ~Disc_quote()\n    {\n        std::cout << \"destructing Dis_quote\\n\";\n    }\n\nprotected:\n    std::size_t quantity = 3;\n    double      discount = 0.0;\n};\n\nbool inline\noperator !=(const Disc_quote& lhs, const Disc_quote& rhs)\n{\n    return Quote(lhs) != Quote(rhs)\n            &&\n            lhs.quantity != rhs.quantity\n            &&\n            lhs.discount != rhs.discount;\n}\n\n#endif // DISC_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.30/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\n\nvoid Limit_quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"max_qty= \" << this->quantity << \" \"\n              << \"discount= \" << this->discount<< \" \\n\";\n}\n"
  },
  {
    "path": "ch15/ex15.30/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"disc_quote.h\"\n\nclass Limit_quote : public Disc_quote\n{\npublic:\n    Limit_quote() = default;\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Disc_quote(b, p, max, disc)  {   }\n\n    double net_price(std::size_t n) const override\n    { return n * price * (n < quantity ? 1 - discount : 1 ); }\n\n    void debug() const override;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.30/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       28  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.30:\n// Write your own version of the Basket class and use it to compute prices\n// for the same transactions as you used in the previous exercises.\n//\n\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <memory>\n#include <fstream>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n#include \"disc_quote.h\"\n#include \"basket.h\"\n\n\nint main()\n{\n    Basket basket;\n\n    for (unsigned i = 0; i != 10; ++i)\n        basket.add_item(Bulk_quote(\"Bible\", 20.6, 20, 0.3));\n\n    for (unsigned i = 0; i != 10; ++i)\n        basket.add_item(Bulk_quote(\"C++Primer\", 30.9, 5, 0.4));\n\n    for (unsigned i = 0; i != 10; ++i)\n        basket.add_item(Quote(\"CLRS\", 40.1));\n\n    std::ofstream log(\"log.txt\", std::ios_base::app|std::ios_base::out);\n\n    basket.total_receipt(log);\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.30/quote.cpp",
    "content": "#include \"quote.h\"\n\nvoid Quote::debug() const\n{\n    std::cout //<< \"data members of this class:\\n\"\n              << \"bookNo= \" <<this->bookNo << \" \"\n              << \"price= \" <<this->price<< \" \\n\";\n}\n\n// non-member\ndouble print_total(std::ostream &os, const Quote &item, size_t n)\n{\n    // depending on the type of the object bound to the item parameter\n    // calls either Quote::net_price or Bulk_quote::net_price\n    double ret = item.net_price(n);\n    os << \"ISBN: \" << item.isbn() // calls Quote::isbn\n       << \" # sold: \" << n << \" total due: \" << ret << std::endl;\n     return ret;\n}\n"
  },
  {
    "path": "ch15/ex15.30/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\n    friend bool operator !=(const Quote& lhs, const Quote& rhs);\npublic:\n    Quote() { std::cout << \"default constructing Quote\\n\"; }\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { std::cout << \"Quote : constructor taking 2 parameters\\n\"; }\n\n    // copy constructor\n    Quote(const Quote& q) : bookNo(q.bookNo), price(q.price)\n    { std::cout << \"Quote: copy constructing\\n\"; }\n\n    // move constructor\n    Quote(Quote&& q) noexcept : bookNo(std::move(q.bookNo)), price(std::move(q.price))\n    { std::cout << \"Quote: move constructing\\n\"; }\n\n    // copy =\n    Quote& operator =(const Quote& rhs)\n    {\n        if(*this != rhs)\n        {\n            bookNo = rhs.bookNo;\n            price  = rhs.price;\n        }\n        std::cout << \"Quote: copy =() \\n\";\n\n        return *this;\n    }\n\n    // move =\n    Quote& operator =(Quote&& rhs)  noexcept\n    {\n        if(*this != rhs)\n        {\n            bookNo = std::move(rhs.bookNo);\n            price  = std::move(rhs.price);\n        }\n        std::cout << \"Quote: move =!!!!!!!!! \\n\";\n\n        return *this;\n    }\n\n    // clone self\n    virtual Quote* clone() const & { return new Quote(*this); }\n    virtual Quote* clone() &&      { return new Quote(std::move(*this)); }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n    virtual void    debug() const;\n\n    virtual ~Quote()\n    {\n        std::cout << \"destructing Quote\\n\";\n    }\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 10.0;\n};\n\nbool inline\noperator !=(const Quote& lhs, const Quote& rhs)\n{\n    return lhs.bookNo != rhs.bookNo\n           &&\n           lhs.price  != rhs.price;\n}\n\n// non-member\ndouble print_total(std::ostream &os, const Quote &item, size_t n);\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.31.32.33.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       28  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.31:\n// Given that s1, s2, s3, and s4 are all strings, determine what objects are created in the following expressions:\n//     (a) Query(s1) | Query(s2) & ~ Query(s3);\n//          OrQuery, AndQuery, NotQuery, WordQuery\n//     (b) Query(s1) | (Query(s2) & ~ Query(s3));\n//          the same as the previous one\n//     (c) (Query(s1) & (Query(s2)) | (Query(s3) & Query(s4)));\n//         OrQuery, AndQuery, WordQuery\n// Exercise 15.32:\n// What happens when an object of type Query is copied, moved, assigned, and destroyed?\n//  copy:\n//  While being copied, the synthesized copy constructor is called. It copies the data member\n//  into the new object. Since in this case, the data member is a shared pointer, while\n//  copying, the corresponding shared pointer points to the same address and\n//  the use count from the both shared pointer becomes 2.\n//\n//  move:\n//  while being moved, the synthesized move constructor is called. It moves the data member\n//  into the new object. In this case, the shared pointer from the newly created\n//  object will point to the address to which the original shared pointer pointed .\n//  After the move operation, the use count of the shared pointer in the new object is 1,\n//  whereas the pointer from the original object becomes nullptr.\n//\n//  copy assignment:\n//  The synthesized copy assignment will be called. The outcome of this\n//  operation is identical with the copy operation.\n//\n//  move assignment:\n//  The synthesized move assignment will be called. The rest is the same as\n//  the move operation.\n//\n//  destroy:\n//  The synthesized destructor will be called. It will call the destructor of\n//  shared_ptr which decrements the use count. If the count becomes zero, the destructor\n//  from shared_ptr will delete the resources it point to.\n//\n// Exercise 15.33:\n// What about objects of type Query_base?\n//  Managed by the synthesized version. Since Query_base a abstract class, the object of\n//  this type is essentially a subobject of its derived class.\n//\n\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <memory>\n#include <fstream>\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query_base.h\"\n#include \"query.h\"\n\n\n// this class is a simulation for class Query used to answer ex15.32\nclass Foo\n{\npublic:\n    Foo(const std::vector<std::string>& t) :\n        text(new std::vector<std::string>(t)) { }\n\nprivate:\n    std::shared_ptr<std::vector<std::string>> text;\n\n};\nint main()\n{\n    std::vector<std::string> v = { \"alan\",\"alan\",\"alan\",\"alan\",\"alan\" };\n\n    Foo foo(v);\n\n    Foo bar = std::move(foo);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/StrBlob.h",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced. Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n * \tPearson Education, Inc.\n * \tRights and Permissions Department\n * \tOne Lake Street\n * \tUpper Saddle River, NJ  07458\n * \tFax: (201) 236-3290\n*/\n\n#ifndef STRBLOB_H\n#define STRBLOB_H\n\n#include <vector>\n#include <string>\n#include <initializer_list>\n#include <memory>\n#include <stdexcept>\n\n// forward declaration needed for friend declaration in StrBlob\nclass StrBlobPtr;\n\nclass StrBlob\n{\n\tfriend class StrBlobPtr;\npublic:\n    typedef std::vector<std::string>::size_type size_type;\n\n\t// constructors\n    StrBlob() : data(std::make_shared<std::vector<std::string>>()) { }\n    StrBlob(std::initializer_list<std::string> il);\n\n\t// size operations\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    // add and remove elements\n    void push_back(const std::string &t) { data->push_back(t); }\n    void pop_back();\n\n    // element access\n    std::string& front();\n    std::string& back();\n\n\t// interface to StrBlobPtr\n\tStrBlobPtr begin();  // can't be defined until StrBlobPtr is\n    StrBlobPtr end();\nprivate:\n    std::shared_ptr<std::vector<std::string>> data; \n    // throws msg if data[i] isn't valid\n    void check(size_type i, const std::string &msg) const;\n};\n\n// constructor\ninline\nStrBlob::StrBlob(std::initializer_list<std::string> il): \n              data(std::make_shared<std::vector<std::string>>(il)) { }\n\n// StrBlobPtr throws an exception on attempts to access a nonexistent element \nclass StrBlobPtr\n{\n\tfriend bool eq(const StrBlobPtr&, const StrBlobPtr&);\npublic:\n    StrBlobPtr(): curr(0) { }\n    StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }\n\n    // newly overloaded why?\n    StrBlobPtr(const StrBlob &a, const size_t sz = 0) : wptr(a.data), curr(sz) { }\n\n    std::string& deref() const;\n    StrBlobPtr& incr();       // prefix version\n    StrBlobPtr& decr();       // prefix version\nprivate:\n    // check returns a shared_ptr to the vector if the check succeeds\n    std::shared_ptr<std::vector<std::string>> \n        check(std::size_t, const std::string&) const;\n\n    // store a weak_ptr, which means the underlying vector might be destroyed\n    std::weak_ptr<std::vector<std::string>> wptr;  \n    std::size_t curr;      // current position within the array\n};\n\ninline\nstd::string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\"); \n    return (*p)[curr];  // (*p) is the vector to which this object points\n}\n\ninline\nstd::shared_ptr<std::vector<std::string>> \nStrBlobPtr::check(std::size_t i, const std::string &msg) const\n{\n    auto ret = wptr.lock();   // is the vector still around?\n    if (!ret)\n        throw std::runtime_error(\"unbound StrBlobPtr\");\n\n    if (i >= ret->size()) \n        throw std::out_of_range(msg);\n    return ret; // otherwise, return a shared_ptr to the vector\n}\n\n// prefix: return a reference to the incremented object\ninline\nStrBlobPtr& StrBlobPtr::incr()\n{\n    // if curr already points past the end of the container, can't increment it\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;       // advance the current state\n    return *this;\n}\n\ninline\nStrBlobPtr& StrBlobPtr::decr()\n{\n    // if curr is zero, decrementing it will yield an invalid subscript\n    --curr;       // move the current state back one element}\n    check(-1, \"decrement past begin of StrBlobPtr\");\n    return *this;\n}\n\n// begin and end members for StrBlob\ninline\nStrBlobPtr\nStrBlob::begin() \n{\n\treturn StrBlobPtr(*this);\n}\n\ninline\nStrBlobPtr\nStrBlob::end() \n{\n\tauto ret = StrBlobPtr(*this, data->size());\n    return ret; \n}\n\n// named equality operators for StrBlobPtr\ninline\nbool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n\tauto l = lhs.wptr.lock(), r = rhs.wptr.lock();\n\t// if the underlying vector is the same \n\tif (l == r) \n\t\t// then they're equal if they're both null or \n\t\t// if they point to the same element\n\t\treturn (!r || lhs.curr == rhs.curr);\n\telse\n\t\treturn false; // if they point to difference vectors, they're not equal\n}\n\ninline\nbool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n\treturn !eq(lhs, rhs); \n}\n#endif\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/andquery.cpp",
    "content": "#include \"andquery.h\"\n\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/andquery.h",
    "content": "#ifndef ANDQUERY_H\n#define ANDQUERY_H\n\n\n#include \"binaryquery.h\"\n\nclass AndQuery : public BinaryQuery\n{\n    friend Query operator&(const Query&, const Query&);\n    AndQuery(const Query& left, const Query& right):\n        BinaryQuery(left, right, \"&\")\n    {\n        std::cout << \"AndQuery::AndQuery()\\n\";\n    }\n\n    // @note: inherits rep and define eval\n\n    QueryResult eval(const TextQuery &) const override\n    {\n        // this is just a placeholder rather than the real definition\n    }\n};\n\ninline Query operator& (const Query& lhs, const Query& rhs)\n{\n    return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));\n}\n\n#endif // ANDQUERY_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/binaryquery.cpp",
    "content": "#include \"binaryquery.h\"\n\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/binaryquery.h",
    "content": "#ifndef BINARYQUERY_H\n#define BINARYQUERY_H\n\n#include \"query_base.h\"\n#include \"query.h\"\n\n\n\n/**\n * @brief The BinaryQuery class\n *An abstract class holds data needed by the query types that operate on two operands\n */\nclass BinaryQuery : public Query_base\n{\nprotected:\n    BinaryQuery(const Query&l, const Query& r, std::string s):\n        lhs(l), rhs(r), opSym(s)\n    {\n        std::cout << \"BinaryQuery::BinaryQuery()  where s=\" + s + \"\\n\";\n    }\n\n    // @note:  abstract class: BinaryQuery doesn't define eval\n\n    std::string rep() const override\n    {\n        std::cout << \"BinaryQuery::rep()\\n\";\n        return \"(\" + lhs.rep() + \" \"\n                   + opSym + \" \"\n                + rhs.rep() + \")\";\n    }\n\n    Query lhs, rhs;\n    std::string opSym;\n};\n\n#endif // BINARYQUERY_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       31  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.34: For the expression built in Figure 15.3 (p. 638):\n//     (a) List the constructors executed in processing that expression.\n//          Query q = Query(\"fiery\") & Query(\"bird\") | Query(\"wind\");\n//      1:  Query::Query(const std::string& s) where s == \"fiery\",\"bird\" and \"wind\"\n//      2:  WordQuery::WordQuery(const std::string& s) where s == \"fiery\",\"bird\" and \"wind\"\n//      3:  AndQuery::AndQuery(const Query& left, const Query& right);\n//      4:  BinaryQuery(const Query&l, const Query& r, std::string s);\n//      5:  Query::Query(std::shared_ptr<Query_base> query) 2times\n//      6:  OrQuery::OrQuery(const Query& left, const Query& right);\n//      7:  BinaryQuery(const Query&l, const Query& r, std::string s);\n//      8:  Query::Query(std::shared_ptr<Query_base> query) 2times\n//\n//     (b) List the calls to rep that are made from cout << q.\n//      query.rep() inside the operator <<()\n//      q->rep()    insede the member function rep()\n//      OrQuery::rep() which is inherited from BinaryQuery\n//      BinaryQuery::rep()\n//      Query::rep() for lhs and rhs\n//          for rhs which is a WordQuery : WordQuery::rep() where query_word(\"wind\") is returned.\n//          for lhs which is an AndQuery:\n//              AndQuery::rep()     --which is inherited from BinaryQuery\n//              BinaryQuer::rep()\n//                  for rhs: WordQuery::rep()   where query_word(\"fiery\") is returned\n//                  for lhs: WordQuery::rep()   where query_word(\"bird\" ) is returned\n//\n//     (c) List the calls to eval made from q.eval().\n//      q.eval()\n//      q->rep()    where q is a pointer to OrQuary\n//      QueryResult eval(const TextQuery& )const override -- is called but this one has not been defined yet.\n//\n// Exercise 15.35:\n// Implement the Query and Query_base classes, including a definition of\n// rep but omitting the definition of eval.\n//\n// Exercise 15.36:\n// Put print statements in the constructors and rep members and run your code\n// to check your answers to (a) and (b) from the first exercise.\n//\n//      Query q = Query(\"fiery\") & Query(\"bird\") | Query(\"wind\");\n//\n//     WordQuery::WordQuery(wind)\n//     Query::Query(const std::string& s) where s=wind\n//     WordQuery::WordQuery(bird)\n//     Query::Query(const std::string& s) where s=bird\n//     WordQuery::WordQuery(fiery)\n//     Query::Query(const std::string& s) where s=fiery\n//     BinaryQuery::BinaryQuery()  where s=&\n//     AndQuery::AndQuery()\n//     Query::Query(std::shared_ptr<Query_base> query)\n//     BinaryQuery::BinaryQuery()  where s=|\n//     OrQuery::OrQuery\n//     Query::Query(std::shared_ptr<Query_base> query)\n//     Press <RETURN> to close this window...\n//\n//\n//\n//      std::cout << q <<std::endl;\n//\n//     Query::rep()\n//     BinaryQuery::rep()\n//     Query::rep()\n//     WodQuery::rep()\n//     Query::rep()\n//     BinaryQuery::rep()\n//     Query::rep()\n//     WodQuery::rep()\n//     Query::rep()\n//     WodQuery::rep()\n//     ((fiery & bird) | wind)\n//     Press <RETURN> to close this window...\n//\n// Exercise 15.37:\n// What changes would your classes need if the derived classes had\n// members of type shared_ptr<Query_base> rather than of type Query?\n//      not done\n//\n// Exercise 15.38:\n// Are the following declarations legal?\n// If not, why not? If so, explain what the declarations mean.\n//     BinaryQuery a = Query(\"fiery\") & Query(\"bird\");\n//          Illegal. Because BinaryQuery is an abstract class.\n//     AndQuery b = Query(\"fiery\") & Query(\"bird\");\n//          Illegal. Because operator & returns a Query which can not convert to an AndQuery object.\n//     OrQuery c = Query(\"fiery\") & Query(\"bird\");\n//          Illegal. Because operator & returns a Query which can not convert to an OrQuery object.\n//\n\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <memory>\n#include <fstream>\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query_base.h\"\n#include \"query.h\"\n#include \"andquery.h\"\n#include \"orquery.h\"\n\n\n\nint main()\n{\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/notquery.cpp",
    "content": "#include \"notquery.h\"\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/notquery.h",
    "content": "#ifndef NOTQUERY_H\n#define NOTQUERY_H\n#include \"query_base.h\"\n#include \"query.h\"\n\n\n/**\n * @brief The NotQuery class\n *\n *The ~ operator generates a NotQuery, which holds a Query,\n *which it negates.\n */\nclass NotQuery : public Query_base\n{\n    friend Query operator~(const Query& operand);\n    NotQuery(const Query& q): query(q)\n    {\n        std::cout << \"NotQuery::NotQuery()\\n\";\n    }\n\n    // virtuals:\n    std::string rep() const override\n    {\n        std::cout << \"NotQuery::rep()\\n\";\n        return \"~(\" + query.rep() + \")\";\n    }\n\n    QueryResult eval(const TextQuery &) const override;\n\n    Query query;\n};\n\ninline Query operator~(const Query& operand)\n{\n    return std::shared_ptr<Query_base>(new NotQuery(operand));\n    //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // note : There is an imlplicit conversion here.\n    //        The Query constructor that takes shared_ptr is not\n    //        \"explicit\", thus the compiler allows this conversion.\n}\n\n#endif // NOTQUERY_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/orquery.cpp",
    "content": "#include \"orquery.h\"\n\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/orquery.h",
    "content": "#ifndef ORQUERY_H\n#define ORQUERY_H\n\n#include \"binaryquery.h\"\n\nclass OrQuery :public BinaryQuery\n{\n    friend Query operator|(const Query&, const Query&);\n    OrQuery(const Query& left, const Query& right):\n        BinaryQuery(left, right, \"|\")\n    {\n        std::cout << \"OrQuery::OrQuery\\n\";\n    }\n\n    QueryResult eval(const TextQuery& )const override\n    {\n        //place holder\n    }\n};\n\ninline Query operator|(const Query &lhs, const Query& rhs)\n{\n    return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));\n}\n\n#endif // ORQUERY_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/query.cpp",
    "content": "#include \"query.h\"\n\n\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/query.h",
    "content": "#ifndef QUERY_H\n#define QUERY_H\n\n#include <iostream>\n#include <string>\n#include <memory>\n#include \"query_base.h\"\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"wordquery.h\"\n\n\n\n/**\n * @brief interface class to manage the Query_base inheritance hierachy\n */\nclass Query\n{\n    friend Query operator~(const Query&);\n    friend Query operator|(const Query&, const Query&);\n    friend Query operator&(const Query&, const Query&);\npublic:\n    // build a new WordQuery\n    Query(const std::string& s) : q(new WordQuery(s))\n    {\n        std::cout << \"Query::Query(const std::string& s) where s=\"+s+\"\\n\";\n    }\n\n    // interface functions: call the corresponding Query_base operatopns\n    QueryResult eval(const TextQuery& t) const\n    { return q->eval(t); }\n    std::string rep() const\n    {\n        std::cout << \"Query::rep() \\n\";\n        return q->rep();\n    }\n\nprivate:\n    // constructor only for friends\n    Query(std::shared_ptr<Query_base> query) :\n        q(query)\n    {\n        std::cout << \"Query::Query(std::shared_ptr<Query_base> query)\\n\";\n    }\n    std::shared_ptr<Query_base> q;\n};\n\ninline std::ostream&\noperator << (std::ostream& os, const Query& query)\n{\n    // make a virtual call through its Query_base pointer to rep();\n    return os << query.rep();\n}\n\n#endif // QUERY_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/query_base.cpp",
    "content": "#include \"query_base.h\"\n\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/query_base.h",
    "content": "#ifndef QUERY_BASE_H\n#define QUERY_BASE_H\n#include \"textquery.h\"\n#include \"queryresult.h\"\n\n/**\n * @brief abstract class acts as a base class for all concrete query types\n *        all members are private.\n */\nclass Query_base\n{\n    friend class Query;\nprotected:\n    using line_no = TextQuery::line_no; //  used in the eval function\n    virtual ~Query_base() = default;\n\nprivate:\n    // returns QueryResult that matches this query\n    virtual QueryResult eval(const TextQuery&) const = 0;\n\n    // a string representation of this query\n    virtual std::string rep() const = 0;\n};\n\n#endif // QUERY_BASE_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/queryresult.cpp",
    "content": "/***************************************************************************\n *  @file       queryresult.cpp\n *  @author     Alan.W\n *  @date       30  DEC 2013\n *  @remark     using class StrBlob\n ***************************************************************************/\n\n\n#include \"queryresult.h\"\n\n\n/**\n * @brief   print the result to the output stream specified.\n * @note    class QueryResult's friend\n */\nstd::ostream\n&print(std::ostream &os, const QueryResult &qr)\n{\n    os << qr.sought << \" occurs \" << qr.sp_lines->size() << \" \"\n       << \"times\"   <<  \"\\n\";\n\n    // print each line in which the word appears\n    for ( auto &index : *qr.sp_lines)\n    {\n        os << \"\\t(line \" << index + 1 << \") \";\n        const StrBlobPtr wp(qr.file, index);\n        os << wp.deref() << \"\\n\";\n    }\n    return os;\n\n}\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/queryresult.h",
    "content": "/***************************************************************************\n *  @file       queryresult.h\n *  @author     Alan.W\n *  @date       30  DEC 2013\n *  @remark     using class StrBlob\n ***************************************************************************/\n\n//\n// Exercise 12.33:\n// In Chapter 15 we’ll extend our query system and will need some additional\n// members in the QueryResult class.\n//\n// Add members named begin and end that\n// return iterators into the set of line numbers returned by a given query,\n// and a member named get_file that returns a shared_ptr to the file in the\n// QueryResult object.\n//\n\n#ifndef QUERYRESULT_H\n#define QUERYRESULT_H\n\n#include <iostream>\n#include <memory>\n#include <set>\n#include <vector>\n#include <string>\n#include \"textquery.h\"\n\n/**\n * @brief Query Result\n */\nclass QueryResult\n{\n    friend std::ostream& print(std::ostream&, const QueryResult&);\n\npublic:\n    // constructor\n    QueryResult(std::string s,\n                std::shared_ptr<std::set<TextQuery::line_no>> sp_l,\n                StrBlob f) :\n        sought(s), sp_lines(sp_l), file(f) { }\n\n    // added for ex12.33\n    // ? Think about wether the \"const\"s here are expected.\n    const StrBlob& get_file() const{ return file; }\n\n    std::set<TextQuery::line_no>::iterator\n    begin() { return sp_lines->begin(); }\n\n    std::set<TextQuery::line_no>::iterator\n    end()   { return sp_lines->end();   }\n\n\n\nprivate:\n    // three data members\n    std::string sought;\n    std::shared_ptr<std::set<TextQuery::line_no>> sp_lines;\n    StrBlob file;\n\n};\n\n/**\n * @brief print the result to the output stream specified.\n */\nstd::ostream&\nprint(std::ostream&, const QueryResult &);\n#endif // QUERYRESULT_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/textquery.cpp",
    "content": "/***************************************************************************\n *  @file       textquery.cpp\n *  @author     Alan.W\n *  @date       30  DEC 2013\n *  @remark     The TextQuery class using StrBlob\n ***************************************************************************/\n\n//\n// Exercise 12.32:\n// Rewrite the TextQuery and QueryResult classes to use a StrBlob instead of a\n// vector<string> to hold the input file.\n//  Relevant post on Stack Overflow:\n//  http://stackoverflow.com/questions/20823225/what-will-happen-if-a-user-defined-constructor-omits-ininitialization-for-data-m\n//\n\n#include \"textquery.h\"\n#include \"queryresult.h\"\n#include <iostream>\n#include <sstream>\n#include <iterator>\n\n/**\n * @brief constructor using StrBlob.\n */\nTextQuery::TextQuery(std::ifstream &fin) :\n    file(StrBlob()),\n    wordMap(std::map<std::string, std::shared_ptr<std::set<line_no>>>())\n{\n    std::string line;\n\n    // each line\n    while(std::getline(fin, line))\n    {\n        file.push_back(line);\n        int n = file.size() - 1;    // the current line number\n\n        // each word\n        std::stringstream lineSteam(line);\n        std::string word;\n        while(lineSteam >> word)\n        {\n            std::shared_ptr<std::set<line_no>>&                          \n                           sp_lines = wordMap[word];\n            // if null\n            if(!sp_lines)\n            {\n                sp_lines.reset(new std::set<line_no>);\n            }\n            sp_lines->insert(n);\n        }\n    }\n}\n\n/**\n * @brief do a query opertion and return QueryResult object.\n */\nQueryResult\nTextQuery::query(const std::string &sought) const\n{\n    // dynamicaly allocated set used for the word does not appear.\n    static std::shared_ptr<std::set<line_no>> noData(new std::set<line_no>);\n\n    // fetch the iterator to the matching element in the map<word, lines>.\n    //std::map<std::string, std::shared_ptr<std::set<index_Tp>>>::const_iterator\n    auto iter = wordMap.find(sought);\n    if(iter == wordMap.end())\n        return QueryResult(sought, noData, file);\n    else\n        return QueryResult(sought, iter->second, file);\n}\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/textquery.h",
    "content": "/***************************************************************************\n *  @file       textquery.h\n *  @author     Alan.W\n *  @date       30  DEC 2013\n *  @remark     The TextQuery class using StrBlob\n ***************************************************************************/\n\n//\n// Exercise 12.32:\n// Rewrite the TextQuery and QueryResult classes to use a StrBlob instead of a\n// vector<string> to hold the input file.\n//  Relevant post on Stack Overflow:\n//  http://stackoverflow.com/questions/20823225/what-will-happen-if-a-user-defined-constructor-omits-ininitialization-for-data-m\n//\n\n\n#ifndef TEXTQUERY_H\n#define TEXTQUERY_H\n\n#include \"StrBlob.h\"\n#include <map>\n#include <set>\n#include <string>\n#include <memory>\n#include <fstream>\n\nclass QueryResult;\n\n/**\n * @brief The TextQuery class using StrBlob\n */\nclass TextQuery\n{\npublic:\n    typedef StrBlob::size_type line_no;\n\n    // constructor\n    TextQuery(std::ifstream& fin);\n\n    // query operation\n    QueryResult query(const std::string&) const;\n\nprivate:\n    // data members\n    StrBlob file;\n\n    std::map<std::string,\n             std::shared_ptr<std::set<line_no>>> wordMap;\n\n};\n\n#endif // TEXTQUERY_H\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/wordquery.cpp",
    "content": "#include \"wordquery.h\"\n\n"
  },
  {
    "path": "ch15/ex15.34.35.36.38/wordquery.h",
    "content": "#ifndef WORDQUERY_H\n#define WORDQUERY_H\n\n#include \"query_base.h\"\n\n/**\n * @brief The WordQuery class\n *The only class that actually performs a query on the given TextQuery object.\n *No public members defined in this class. All operation are through the friend\n *class Query.\n */\nclass WordQuery : public Query_base\n{\n    // class Query uses the WordQuery constructor\n    friend class Query;\n    WordQuery(const std::string& s):\n        query_word(s)\n    {\n        std::cout << \"WordQuery::WordQuery(\" + s + \")\\n\";\n    }\n\n\n    // virtuals:\n    QueryResult eval(const TextQuery& t) const override\n    {   return t.query(query_word); }\n    std::string rep() const override\n    {\n        std::cout << \"WodQuery::rep()\\n\";\n        return query_word;\n    }\n\n\n    std::string query_word;\n};\n\n#endif // WORDQUERY_H\n"
  },
  {
    "path": "ch15/ex15.39.40/StrBlob.h",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced. Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n * \tPearson Education, Inc.\n * \tRights and Permissions Department\n * \tOne Lake Street\n * \tUpper Saddle River, NJ  07458\n * \tFax: (201) 236-3290\n*/\n\n#ifndef STRBLOB_H\n#define STRBLOB_H\n\n#include <vector>\n#include <string>\n#include <initializer_list>\n#include <memory>\n#include <stdexcept>\n\n// forward declaration needed for friend declaration in StrBlob\nclass StrBlobPtr;\n\nclass StrBlob\n{\n\tfriend class StrBlobPtr;\npublic:\n    typedef std::vector<std::string>::size_type size_type;\n\n\t// constructors\n    StrBlob() : data(std::make_shared<std::vector<std::string>>()) { }\n    StrBlob(std::initializer_list<std::string> il);\n\n\t// size operations\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    // add and remove elements\n    void push_back(const std::string &t) { data->push_back(t); }\n    void pop_back();\n\n    // element access\n    std::string& front();\n    std::string& back();\n\n\t// interface to StrBlobPtr\n\tStrBlobPtr begin();  // can't be defined until StrBlobPtr is\n    StrBlobPtr end();\nprivate:\n    std::shared_ptr<std::vector<std::string>> data; \n    // throws msg if data[i] isn't valid\n    void check(size_type i, const std::string &msg) const;\n};\n\n// constructor\ninline\nStrBlob::StrBlob(std::initializer_list<std::string> il): \n              data(std::make_shared<std::vector<std::string>>(il)) { }\n\n// StrBlobPtr throws an exception on attempts to access a nonexistent element \nclass StrBlobPtr\n{\n\tfriend bool eq(const StrBlobPtr&, const StrBlobPtr&);\npublic:\n    StrBlobPtr(): curr(0) { }\n    StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }\n\n    // newly overloaded why?\n    StrBlobPtr(const StrBlob &a, const size_t sz = 0) : wptr(a.data), curr(sz) { }\n\n    std::string& deref() const;\n    StrBlobPtr& incr();       // prefix version\n    StrBlobPtr& decr();       // prefix version\nprivate:\n    // check returns a shared_ptr to the vector if the check succeeds\n    std::shared_ptr<std::vector<std::string>> \n        check(std::size_t, const std::string&) const;\n\n    // store a weak_ptr, which means the underlying vector might be destroyed\n    std::weak_ptr<std::vector<std::string>> wptr;  \n    std::size_t curr;      // current position within the array\n};\n\ninline\nstd::string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\"); \n    return (*p)[curr];  // (*p) is the vector to which this object points\n}\n\ninline\nstd::shared_ptr<std::vector<std::string>> \nStrBlobPtr::check(std::size_t i, const std::string &msg) const\n{\n    auto ret = wptr.lock();   // is the vector still around?\n    if (!ret)\n        throw std::runtime_error(\"unbound StrBlobPtr\");\n\n    if (i >= ret->size()) \n        throw std::out_of_range(msg);\n    return ret; // otherwise, return a shared_ptr to the vector\n}\n\n// prefix: return a reference to the incremented object\ninline\nStrBlobPtr& StrBlobPtr::incr()\n{\n    // if curr already points past the end of the container, can't increment it\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;       // advance the current state\n    return *this;\n}\n\ninline\nStrBlobPtr& StrBlobPtr::decr()\n{\n    // if curr is zero, decrementing it will yield an invalid subscript\n    --curr;       // move the current state back one element}\n    check(-1, \"decrement past begin of StrBlobPtr\");\n    return *this;\n}\n\n// begin and end members for StrBlob\ninline\nStrBlobPtr\nStrBlob::begin() \n{\n\treturn StrBlobPtr(*this);\n}\n\ninline\nStrBlobPtr\nStrBlob::end() \n{\n\tauto ret = StrBlobPtr(*this, data->size());\n    return ret; \n}\n\n// named equality operators for StrBlobPtr\ninline\nbool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n\tauto l = lhs.wptr.lock(), r = rhs.wptr.lock();\n\t// if the underlying vector is the same \n\tif (l == r) \n\t\t// then they're equal if they're both null or \n\t\t// if they point to the same element\n\t\treturn (!r || lhs.curr == rhs.curr);\n\telse\n\t\treturn false; // if they point to difference vectors, they're not equal\n}\n\ninline\nbool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n\treturn !eq(lhs, rhs); \n}\n#endif\n"
  },
  {
    "path": "ch15/ex15.39.40/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       01  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.39:\n// Implement the Query and Query_base classes. Test your application by\n// evaluating and printing a query such as the one in Figure 15.3 (p. 638).\n//\n// Exercise 15.40:\n// In the OrQuery eval function what would happen if its rhs member returned\n// an empty set? What if its lhs member did so? What if both rhs and lhs\n// returned empty sets?\n//  Nothing special will happen.  The codes as following:\n//          std::shared_ptr<std::set<line_no>> ret_lines =\n//                  std::make_shared<std::set<line_no>>(left.begin(), left.end());\n//                 ^^^^^^^^^^^^^^^^\n//  Since std::make_shared will allocate dynamically a new std::set, nothing will\n//  be added into this std::set if any set is empty.The codes in main function\n//  proves this.\n//\n\n#include <iostream>\n#include <string>\n#include <vector>\n#include <memory>\n#include <fstream>\n\n#include \"textquery.h\"\n#include \"query.h\"\n\nint main()\n{\n    std::ifstream file(\"test.txt\");\n\n    TextQuery tQuery(file);\n\n    Query q = Query(\"fieryzzz\")  | Query(\"wind\");\n\n    std::cout << q.eval(tQuery);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.39.40/query.cpp",
    "content": "#include <algorithm>\n#include \"query.h\"\n/**\n * @brief AndQuery::eval\n * @return the intersection of its operands' result sets\n */\nQueryResult AndQuery::eval(const TextQuery &text) const\n{\n    // virtual calls through the Query operands to get result sets for the operands\n    QueryResult left = lhs.eval(text), right = rhs.eval(text);\n\n    // set to hold the intersection of the left and right\n    std::shared_ptr<std::set<line_no>>\n                   ret_lines = std::make_shared<std::set<line_no>>();\n\n    // writes the intersection of two ranges to a destination iterator\n    std::set_intersection(left.begin(), left.end(),\n                          right.begin(), right.end(),\n                          std::inserter(*ret_lines, ret_lines->begin()));\n\n    return QueryResult(rep(), ret_lines, left.get_file());\n}\n\n/**\n * @brief OrQuery::eval\n * @return the union of its operands' result sets\n */\nQueryResult OrQuery::eval(const TextQuery &text) const\n{\n    QueryResult right = rhs.eval(text), left= lhs.eval(text);\n\n    // copy the left-hand operand into the result set\n    std::shared_ptr<std::set<line_no>> ret_lines =\n            std::make_shared<std::set<line_no>>(left.begin(), left.end());\n\n    // inert lines from the right-hand operand\n    ret_lines->insert(right.begin(), right.end());\n\n    return QueryResult(rep(), ret_lines, left.get_file());\n}\n\n/**\n * @brief NotQuery::eval\n * @return the lines not in its operand's result set\n */\nQueryResult NotQuery::eval(const TextQuery &text) const\n{\n    // virtual call to eval through the Query operand\n    QueryResult result = query.eval(text);\n\n    // start out with an empty result set\n    std::shared_ptr<std::set<line_no>>\n            ret_lines = std::make_shared<std::set<line_no>>();\n\n    std::set<TextQuery::line_no>::iterator\n            begin = result.begin(),\n            end   = result.end();\n\n    StrBlob::size_type sz = result.get_file().size();\n\n    for(std::size_t n = 0; n != sz; ++n)\n    {\n        if(begin == end || *begin != n)\n            ret_lines->insert(n);\n        else if (begin != end)\n            ++begin;\n    }\n\n    return QueryResult(rep(), ret_lines, result.get_file());\n}"
  },
  {
    "path": "ch15/ex15.39.40/query.h",
    "content": "#ifndef QUERY_H\n#define QUERY_H\n\n#include <iostream>\n#include <string>\n#include <memory>\n#include \"textquery.h\"\n\n/**\n * @brief abstract class acts as a base class for all concrete query types\n *        all members are private.\n */\nclass Query_base\n{\n    friend class Query;\nprotected:\n    using line_no = TextQuery::line_no; //  used in the eval function\n    virtual ~Query_base() = default;\n\nprivate:\n    // returns QueryResult that matches this query\n    virtual QueryResult eval(const TextQuery&) const = 0;\n\n    // a string representation of this query\n    virtual std::string rep() const = 0;\n};\n\n/**\n * @brief The WordQuery class\n *The only class that actually performs a query on the given TextQuery object.\n *No public members defined in this class. All operation are through the friend\n *class Query.\n */\nclass WordQuery : public Query_base\n{\n    // class Query uses the WordQuery constructor\n    friend class Query;\n    WordQuery(const std::string& s):\n        query_word(s)\n    {\n        std::cout << \"WordQuery::WordQuery(\" + s + \")\\n\";\n    }\n\n\n    // virtuals:\n    QueryResult eval(const TextQuery& t) const override\n    {   return t.query(query_word); }\n    std::string rep() const override\n    {\n        std::cout << \"WodQuery::rep()\\n\";\n        return query_word;\n    }\n\n\n    std::string query_word;\n};\n\n/**\n * @brief interface class to manage the Query_base inheritance hierachy\n */\nclass Query\n{\n    friend Query operator~(const Query&);\n    friend Query operator|(const Query&, const Query&);\n    friend Query operator&(const Query&, const Query&);\n\npublic:\n    // build a new WordQuery\n    Query(const std::string& s) : q(new WordQuery(s))\n    {\n        std::cout << \"Query::Query(const std::string& s) where s=\"+s+\"\\n\";\n    }\n\n    // interface functions: call the corresponding Query_base operatopns\n    QueryResult eval(const TextQuery& t) const\n    { return q->eval(t); }\n    std::string rep() const\n    {\n        std::cout << \"Query::rep() \\n\";\n        return q->rep();\n    }\n\nprivate:\n    // constructor only for friends\n    Query(std::shared_ptr<Query_base> query) :\n        q(query)\n    {\n        std::cout << \"Query::Query(std::shared_ptr<Query_base> query)\\n\";\n    }\n    std::shared_ptr<Query_base> q;\n};\n\ninline std::ostream&\noperator << (std::ostream& os, const Query& query)\n{\n    // make a virtual call through its Query_base pointer to rep();\n    return os << query.rep();\n}\n\n/**\n * @brief The BinaryQuery class\n *An abstract class holds data needed by the query types that operate on two operands\n */\nclass BinaryQuery : public Query_base\n{\nprotected:\n    BinaryQuery(const Query&l, const Query& r, std::string s):\n        lhs(l), rhs(r), opSym(s)\n    {\n        std::cout << \"BinaryQuery::BinaryQuery()  where s=\" + s + \"\\n\";\n    }\n\n    // @note:  abstract class: BinaryQuery doesn't define eval\n\n    std::string rep() const override\n    {\n        std::cout << \"BinaryQuery::rep()\\n\";\n        return \"(\" + lhs.rep() + \" \"\n                   + opSym + \" \"\n                + rhs.rep() + \")\";\n    }\n\n    Query lhs, rhs;\n    std::string opSym;\n};\n\n/**\n * @brief The OrQuery class\n *\n *The & operator generates a OrQuery, which held by a Query,\n */\nclass OrQuery :public BinaryQuery\n{\n    friend Query operator|(const Query&, const Query&);\n    OrQuery(const Query& left, const Query& right):\n        BinaryQuery(left, right, \"|\")\n    {\n        std::cout << \"OrQuery::OrQuery\\n\";\n    }\n\n    QueryResult eval(const TextQuery& )const override;\n};\n\ninline Query operator|(const Query &lhs, const Query& rhs)\n{\n    return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));\n}\n\n/**\n * @brief The AndQuery class\n *\n *The & operator generates a AndQuery, which held by a Query,\n */\nclass AndQuery : public BinaryQuery\n{\n    friend Query operator&(const Query&, const Query&);\n    AndQuery(const Query& left, const Query& right):\n        BinaryQuery(left, right, \"&\")\n    {\n        std::cout << \"AndQuery::AndQuery()\\n\";\n    }\n\n    // @note: inherits rep and define eval\n\n    QueryResult eval(const TextQuery &) const override;\n};\n\ninline Query operator& (const Query& lhs, const Query& rhs)\n{\n    return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));\n}\n\n/**\n * @brief The NotQuery class\n *\n *The ~ operator generates a NotQuery, which held by a Query,\n *which it negates.\n */\nclass NotQuery : public Query_base\n{\n    friend Query operator~(const Query& operand);\n    NotQuery(const Query& q): query(q)\n    {\n        std::cout << \"NotQuery::NotQuery()\\n\";\n    }\n\n    // virtuals:\n    std::string rep() const override\n    {\n        std::cout << \"NotQuery::rep()\\n\";\n        return \"~(\" + query.rep() + \")\";\n    }\n\n    QueryResult eval(const TextQuery &) const override;\n\n    Query query;\n};\n\ninline Query operator~(const Query& operand)\n{\n    return std::shared_ptr<Query_base>(new NotQuery(operand));\n    //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // note : There is an imlplicit conversion here.\n    //        The Query constructor that takes shared_ptr is not\n    //        \"explicit\", thus the compiler allows this conversion.\n}\n#endif // QUERY_H\n"
  },
  {
    "path": "ch15/ex15.39.40/test.txt",
    "content": "Alice Emma has long flowing red hair.\nHer daddy says when the wind blows\nthrough her hair, it looks almost alive,\nlike a fiery bird in flight.\nA beautiful fiery bird, he tells her,\nmagical but untamed.\n\"Daddy, shush, there is no such thing,\"\nshe tells him, at the same time wanting\nhim to tell her more.\nShyly, she asks, \"I mean, Daddy, is there?\"\n"
  },
  {
    "path": "ch15/ex15.39.40/textquery.cpp",
    "content": "/***************************************************************************\n *  @file       textquery.cpp\n *  @author     Alan.W\n *  @date       30  DEC 2013\n *  @remark     The TextQuery class using StrBlob\n ***************************************************************************/\n\n//\n// Exercise 12.32:\n// Rewrite the TextQuery and QueryResult classes to use a StrBlob instead of a\n// vector<string> to hold the input file.\n//  Relevant post on Stack Overflow:\n//  http://stackoverflow.com/questions/20823225/what-will-happen-if-a-user-defined-constructor-omits-ininitialization-for-data-m\n//\n\n#include \"textquery.h\"\n#include <iostream>\n#include <sstream>\n#include <iterator>\n\n/**\n * @brief constructor using StrBlob.\n */\nTextQuery::TextQuery(std::ifstream &fin) :\n    file(StrBlob()),\n    wordMap(std::map<std::string, std::shared_ptr<std::set<line_no>>>())\n{\n    std::string line;\n\n    // each line\n    while(std::getline(fin, line))\n    {\n        file.push_back(line);\n        int n = file.size() - 1;    // the current line number\n\n        // each word\n        std::stringstream lineSteam(line);\n        std::string word;\n        while(lineSteam >> word)\n        {\n            std::shared_ptr<std::set<line_no>>&                          \n                           sp_lines = wordMap[word];\n            // if null\n            if(!sp_lines)\n            {\n                sp_lines.reset(new std::set<line_no>);\n            }\n            sp_lines->insert(n);\n        }\n    }\n}\n\n/**\n * @brief do a query opertion and return QueryResult object.\n */\nQueryResult\nTextQuery::query(const std::string &sought) const\n{\n    // dynamicaly allocated set used for the word does not appear.\n    static std::shared_ptr<std::set<line_no>> noData(new std::set<line_no>);\n\n    // fetch the iterator to the matching element in the map<word, lines>.\n    //std::map<std::string, std::shared_ptr<std::set<index_Tp>>>::const_iterator\n    auto iter = wordMap.find(sought);\n    if(iter == wordMap.end())\n        return QueryResult(sought, noData, file);\n    else\n        return QueryResult(sought, iter->second, file);\n}\n\n/**\n * @brief   print the result to the output stream specified.\n * @note    class QueryResult's friend\n */\nstd::ostream&\noperator <<(std::ostream &os, const QueryResult &qr)\n{\n    os << qr.sought << \" occurs \" << qr.sp_lines->size() << \" \"\n       << \"times\"   <<  \"\\n\";\n\n    // print each line in which the word appears\n    for ( auto &index : *qr.sp_lines)\n    {\n        os << \"\\t(line \" << index + 1 << \") \";\n        const StrBlobPtr wp(qr.file, index);\n        os << wp.deref() << \"\\n\";\n    }\n    return os;\n\n}"
  },
  {
    "path": "ch15/ex15.39.40/textquery.h",
    "content": "/***************************************************************************\n *  @file       textquery.h\n *  @author     Alan.W\n *  @date       30  DEC 2013\n *  @remark     The TextQuery class using StrBlob\n ***************************************************************************/\n\n//\n// Exercise 12.32:\n// Rewrite the TextQuery and QueryResult classes to use a StrBlob instead of a\n// vector<string> to hold the input file.\n//  Relevant post on Stack Overflow:\n//  http://stackoverflow.com/questions/20823225/what-will-happen-if-a-user-defined-constructor-omits-ininitialization-for-data-m\n//\n\n\n#ifndef TEXTQUERY_H\n#define TEXTQUERY_H\n\n#include \"StrBlob.h\"\n#include <map>\n#include <set>\n#include <string>\n#include <memory>\n#include <fstream>\n\nclass QueryResult;\n\n/**\n * @brief The TextQuery class using StrBlob\n */\nclass TextQuery\n{\npublic:\n    typedef StrBlob::size_type line_no;\n\n    // constructor\n    TextQuery(std::ifstream& fin);\n\n    // query operation\n    QueryResult query(const std::string&) const;\n\nprivate:\n    // data members\n    StrBlob file;\n\n    std::map<std::string,\n             std::shared_ptr<std::set<line_no>>> wordMap;\n\n};\n\n/**\n * @brief Query Result\n */\nclass QueryResult\n{\n    friend std::ostream& operator<<(std::ostream&, const QueryResult&);\n\npublic:\n    // constructor\n    QueryResult(std::string s,\n                std::shared_ptr<std::set<TextQuery::line_no>> sp_l,\n                StrBlob f) :\n        sought(s), sp_lines(sp_l), file(f) { }\n\n    // added for ex12.33\n    // ? Think about wether the \"const\"s here are expected.\n    const StrBlob& get_file() const{ return file; }\n\n    std::set<TextQuery::line_no>::iterator\n    begin() { return sp_lines->begin(); }\n\n    std::set<TextQuery::line_no>::iterator\n    end()   { return sp_lines->end();   }\n\n\n\nprivate:\n    // three data members\n    std::string sought;\n    std::shared_ptr<std::set<TextQuery::line_no>> sp_lines;\n    StrBlob file;\n\n};\n\n/**\n * @brief print the result to the output stream specified.\n */\nstd::ostream&\nprint(std::ostream&, const QueryResult &);\n#endif // TEXTQUERY_H\n"
  },
  {
    "path": "ch15/ex15.4.5.6/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= min_qty ? 1 - discount : 1);\n}\n"
  },
  {
    "path": "ch15/ex15.4.5.6/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include <quote.h>\n\nclass Bulk_quote : public Quote\n{\npublic:\n    Bulk_quote() = default;\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Quote(b, p), min_qty(q), discount(disc)  {   }\n\n    double net_price(std::size_t n) const override;\n\nprivate:\n    std::size_t min_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.4.5.6/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       21  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.4:\n// Which of the following declarations, if any, are incorrect? Explain why.\n//       class Base { ... };\n//      (a) class Derived : public Derived { ... }; //incorrect, deirve from itself\n//      (b) class Derived : private Base { ... };   //incorrect, this is a definition not a declaration\n//      (c) class Derived : public Base;            //incorrect, A derived class is declared like any other class. The declaration\n                                                    //contains the class name but does not include its derivation list.\n                                                    //@ reported by lafener, check #154 for detail.\n// Exercise 15.5:\n// Define your own version of the Bulk_quote class.\n//\n// Exercise 15.6:\n// Test your print_total function from the exercises in § 15.2.1 (p. 595)\n// by passing both Quote and Bulk_quote objects o that function.\n//\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n\ndouble print_total (std::ostream& os, const Quote& item, size_t n);\n\nint main()\n{\n    // ex15.6\n    Quote q(\"textbook\", 10.60);\n    Bulk_quote bq(\"textbook\", 10.60, 10, 0.3);\n\n    print_total(std::cout, q, 12);\n    print_total(std::cout, bq, 12);\n\n    return 0;\n}\n\ndouble print_total(std::ostream &os, const Quote &item, size_t n)\n{\n    double ret = item.net_price(n);\n\n    os << \"ISBN:\" << item.isbn()\n       << \"# sold: \" << n << \" total due: \" << ret << std::endl;\n\n    return ret;\n}\n"
  },
  {
    "path": "ch15/ex15.4.5.6/quote.cpp",
    "content": "#include \"quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.4.5.6/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n\nclass Quote\n{\npublic:\n    Quote() = default;\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n\n    virtual ~Quote() = default;\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 0.0;\n\n};\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.42_b/andquery.cpp",
    "content": "#include \"andquery.h\"\n\n#include <algorithm>\nusing std::set_intersection;\n\n#include <iterator>\nusing std::inserter;\n\n#include <memory>\nusing std::make_shared;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n\nQueryResult\nAndQuery::eval(const TextQuery& text) const\n{\n\tauto left = lhs.eval(text);\n\tauto right = rhs.eval(text);\n\n\tauto ret_lines = make_shared<set<line_no>>();\n\n\tset_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));\n\n\treturn QueryResult(rep(), ret_lines, left.get_file());\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/andquery.h",
    "content": "#ifndef _ANDQUERY_H\n#define _ANDQUERY_H\n\n#include <memory>\nusing std::shared_ptr;\n\n#include \"query.h\"\n#include \"binaryquery.h\"\n\nclass QueryResult;\nclass TextQuery;\n\nclass AndQuery :public BinaryQuery\n{\n\tfriend Query operator&(const Query&, const Query&);\n\tAndQuery(const Query &left, const Query &right) :BinaryQuery(left, right, \"&\"){ }\n\tQueryResult eval(const TextQuery&) const;\n};\n\ninline Query operator&(const Query &lhs, const Query &rhs)\n{\n\treturn shared_ptr<Query_base>(new AndQuery(lhs, rhs));\n}\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/binaryquery.cpp",
    "content": "#include \"binaryquery.h\"\n"
  },
  {
    "path": "ch15/ex15.42_b/binaryquery.h",
    "content": "#ifndef _BINARYQUERY_H\n#define _BINARYQUERY_H\n\n#include <string>\nusing std::string;\n\n#include \"query.h\"\n#include \"query_base.h\"\n\n\nclass BinaryQuery :public Query_base\n{\nprotected:\n\tBinaryQuery(const Query &l, const Query &r, string s) :lhs(l), rhs(r), opSym(s){ }\n\tstring rep() const\n\t{\n\t\treturn \"(\" + lhs.rep() + \" \" + opSym + \" \" + rhs.rep() + \")\";\n\t}\n\n\tQuery lhs, rhs;\n\tstring opSym;\n};\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/main.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::cin; using std::endl;\n\n#include <fstream>\nusing std::ifstream;\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include \"queryhistory.h\"\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n#include \"andquery.h\"\n#include \"orquery.h\"\n#include \"notquery.h\"\n\nint main()\n{\n    ifstream fin(\"test.txt\");\n\tTextQuery text(fin);\n\tQueryHistory history;\n\tQuery q0(\"Alice\");\n\tQuery q1(\"hair\");\n\tQuery q2(\"Daddy\");\n\n\thistory.add_query(q0);\n\thistory.add_query(q1);\n\thistory[0] = history[0] | q2;\n\n\tauto result = history[0].eval(text);\n\tprint(cout, result);\n\t\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/notquery.cpp",
    "content": "#include \"notquery.h\"\n\n#include <memory>\nusing std::make_shared;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n\n\nQueryResult\nNotQuery::eval(const TextQuery &text) const\n{\n\tauto result = query.eval(text);\n\n\tauto ret_lines = make_shared<set<line_no>>();\n\n\tauto beg = result.begin();\n\tauto end = result.end();\n\n\tauto sz = result.get_file()->size();\n\tfor (size_t n = 0; n != sz; ++n)\n\t{\n\t\tif (beg == end || *beg != n)\n\t\t\tret_lines->insert(n);\n\t\telse if (beg != end)\n\t\t\t++beg;\n\t}\n\treturn QueryResult(rep(), ret_lines, result.get_file());\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/notquery.h",
    "content": "#ifndef _NOTQUERY_H\n#define _NOTQUERY_H\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <string>\nusing std::string;\n\n#include \"query.h\"\n#include \"query_base.h\"\n\nclass QueryResult;\nclass TextQuery;\n\nclass NotQuery :public Query_base\n{\n\tfriend Query operator~(const Query&);\n\t//call Query's default copy constructor.\n\tNotQuery(const Query &q) :query(q){ }\n\tstring rep() const{ return \"~(\" + query.rep() + \")\"; }\n\tQueryResult eval(const TextQuery&) const;\n\n\tQuery query;\n};\n\ninline Query operator~(const Query &operand)\n{\n\treturn shared_ptr<Query_base>(new NotQuery(operand));\n}\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/orquery.cpp",
    "content": "#include \"orquery.h\"\n\n#include <memory>\nusing std::make_shared;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n\nQueryResult\nOrQuery::eval(const TextQuery &text) const\n{\n\tauto right = rhs.eval(text);\n\tauto left = lhs.eval(text);\n\tauto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());\n\tret_lines->insert(right.begin(), right.end());\n\treturn QueryResult(rep(), ret_lines, left.get_file());\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/orquery.h",
    "content": "#ifndef _ORQUERY_H\n#define _ORQUERY_H\n\n#include <memory>\nusing std::shared_ptr;\n\n#include \"query.h\"\n#include \"binaryquery.h\"\n\nclass QueryResult;\nclass TextQuery;\n\nclass OrQuery :public BinaryQuery\n{\n\tfriend Query operator|(const Query&, const Query&);\n\tOrQuery(const Query &left, const Query &right) :BinaryQuery(left, right, \"|\"){ }\n\tQueryResult eval(const TextQuery&) const;\n};\n\ninline Query operator|(const Query &lhs, const Query &rhs)\n{\n\treturn shared_ptr<Query_base>(new OrQuery(lhs, rhs));\n}\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/query.cpp",
    "content": "#include \"query.h\"\n\n#include <ostream>\nusing std::ostream;\n\nostream&\noperator<<(ostream &os, const Query &query)\n{\n\treturn os << query.rep();\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/query.h",
    "content": "#ifndef _QUERY_H\n#define _QUERY_H\n\n#include <ostream>\nusing std::ostream;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <string>\nusing std::string;\n\n#include \"query_base.h\"\n#include \"queryresult.h\"\n#include \"wordquery.h\"\n\n\nclass TextQuery;\n\nclass Query\n{\n\tfriend Query operator~(const Query&);\n\tfriend Query operator|(const Query&, const Query&);\n\tfriend Query operator&(const Query&, const Query&);\npublic:\n\tQuery(const string&);\n\t//call QueryResult's default copy constructor.\n\tQueryResult eval(const TextQuery &t) const { return q->eval(t); }\n\tstring rep() const { return q->rep(); }\nprivate:\n\tQuery(shared_ptr<Query_base> query) :q(query){ }\n\tshared_ptr<Query_base> q;\n};\n\nostream & operator<<(ostream &os, const Query &query);\n\ninline Query::Query(const string &s) :q(new WordQuery(s)){ }\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/query_base.cpp",
    "content": "#include \"query_base.h\"\n"
  },
  {
    "path": "ch15/ex15.42_b/query_base.h",
    "content": "#ifndef _QUERY_BASE_H\n#define _QUERY_BASE_H\n\n#include <string>\nusing std::string;\n\n#include \"textquery.h\"\n\nclass Query_base\n{\n\tfriend class Query;\nprotected:\n\tusing line_no = TextQuery::line_no;\n\tvirtual ~Query_base() = default;\nprivate:\n\tvirtual QueryResult eval(const TextQuery&) const = 0;\n\tvirtual string rep() const = 0;\n};\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/queryhistory.cpp",
    "content": "#include \"queryhistory.h\"\n\n#include <memory>\nusing std::shared_ptr; using std::make_shared;\n\nsize_t QueryHistory::add_query(const Query &query)\n{\n\tshared_ptr<Query> p = make_shared<Query>(query);\n\tquery_vec.push_back(p);\n\treturn query_vec.size() - 1;\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/queryhistory.h",
    "content": "#ifndef _QUERYHISTORY_H\n#define _QUERYHISTORY_H\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <vector>\nusing std::vector;\n\n#include \"query.h\"\n\nclass QueryHistory\n{\npublic:\n\tQuery& operator[](size_t n)\n\t{\n\t\treturn *(query_vec[n]);\n\t}\n\n\t//return the assigned number of the  new query\n\tsize_t add_query(const Query&);\nprivate:\n\tvector<shared_ptr<Query>> query_vec;\n};\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/queryresult.cpp",
    "content": "#include \"queryresult.h\"\n\n#include <iostream>\nusing std::ostream;\n\nostream&\nprint(ostream &os, const QueryResult &qr)\n{\n    os <<\"The result of your query \"<< qr.sought <<\" is: \\n\";\n    for (const auto &index: *qr.lines)\n        os << \"\\t(line \" << index + 1 << \")\"\n           << *(qr.file->begin() + index) << \"\\n\";\n    return os;\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/queryresult.h",
    "content": "#ifndef _QUERYRESULT_H\n#define _QUERYRESULT_H\n\n#include <iostream>\nusing std::ostream;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <set>\nusing std::set;\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include \"textquery.h\"\n\n\nclass QueryResult\n{\n    friend ostream& print(ostream&, const QueryResult&);\n\npublic:\n\tQueryResult(string s,\n\t\tshared_ptr<set<TextQuery::line_no>> l,\n\t\tshared_ptr<vector<string>> f) :\n\t\tsought(s), lines(l), file(f){ }\n\n\tset<TextQuery::line_no>::iterator begin(){ return lines->begin(); }\n\tset<TextQuery::line_no>::iterator end(){ return lines->end(); }\n\tshared_ptr<vector<string>> get_file(){ return file; }\n\nprivate:\n    string sought;\n    shared_ptr<set<TextQuery::line_no>> lines;\n    shared_ptr<vector<string>> file;\n};\n\nostream&\nprint(ostream&, const QueryResult&);\n\n#endif \n"
  },
  {
    "path": "ch15/ex15.42_b/test.txt",
    "content": "Alice Emma has long flowing red hair.\nHer Daddy says when the wind blows\nthrough her hair, it looks almost alive,\nlike a fiery bird in flight.\nA beautiful fiery bird, he tells her,\nmagical but untamed.\n\"Daddy, shush, there is no such thing,\"\nshe tells him, at the same time wanting\nhim to tell her more.\nShyly, she asks, \"I mean, Daddy, is there?\""
  },
  {
    "path": "ch15/ex15.42_b/textquery.cpp",
    "content": "#include \"textquery.h\"\n\n#include <fstream>\nusing std::ifstream;\n\n#include <sstream>\nusing std::istringstream;\n\n#include <memory>\nusing std::shared_ptr; using std::make_shared;\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <map>\nusing std::map;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n\n\nTextQuery::TextQuery(ifstream& is) :file(new vector<string>)\n{\n\tusing std::getline;\n\n\tstring text;\n    while(getline(is, text))\n    {\n        file->push_back(text);\n\t\tint n = file->size() - 1;\n\t\tistringstream line(text);\n        string word;\n        while(line >> word)\n        {\n\t\t\tauto p = handlePunct(word);\n\t\t\tfor (auto w : *p)\n\t\t\t{\n\t\t\t\tauto &lines = wm[w];\n\t\t\t\tif (!lines)\n\t\t\t\t\tlines.reset(new set<line_no>);\n\t\t\t\tlines->insert(n);\n\t\t\t}\n        }\n    }\n}\n\nQueryResult TextQuery::query(const string &sought) const\n{\n    static shared_ptr<set<line_no>> nodata(new set<line_no>);\n\n    // fetch the iterator to the matching element in the map<word, lines>.\n    //std::map<std::string, std::shared_ptr<std::set<line_no>>>::const_iterator\n    auto loc = wm.find(sought);\n    if(loc == wm.end())\n        return QueryResult(sought, nodata, file);\n    else\n        return QueryResult(sought, loc->second, file);\n}\n\nshared_ptr<vector<string>> TextQuery::handlePunct(const string &s)\n{\n\tshared_ptr<vector<string>> p =\n\t\tmake_shared<vector<string>>();\n\tsize_t first = 0, index = 0;\n\twhile(index != s.size())\n\t{\n\t\tif (ispunct(s[index]))\n\t\t{\n\t\t\tstring word = s.substr(first, index - first);\n\t\t\tif (!word.empty())\n\t\t\t\tp->push_back(word);\n\t\t\tp->push_back(s.substr(index, 1));\n\t\t\t++index;\n\t\t\tfirst = index;\n\t\t}\n\t\telse\n\t\t\t++index;\n\t}\n\tstring trail = s.substr(first);\n\tif (!trail.empty())\n\t\tp->push_back(trail);\n\n\treturn p;\n}\n"
  },
  {
    "path": "ch15/ex15.42_b/textquery.h",
    "content": "#ifndef _TEXTQUERY_H\n#define _TEXTQUERY_H\n\n#include <fstream>\nusing std::ifstream;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <map>\nusing std::map;\n\n#include <set>\nusing std::set;\n\nclass QueryResult;\n\nclass TextQuery\n{\n\npublic:\n    typedef vector<string>::size_type line_no;\n\n    TextQuery(ifstream&);\n    QueryResult query(const string&) const;\n\nprivate:\n    shared_ptr<vector<string>> file;\n\tmap<string, shared_ptr<set<line_no>>> wm;\n\n\tshared_ptr<vector<string>> handlePunct(const string&);\n};\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_b/wordquery.cpp",
    "content": "#include \"wordquery.h\"\n"
  },
  {
    "path": "ch15/ex15.42_b/wordquery.h",
    "content": "#ifndef _WORDQUERY_H\n#define _WORDQUERY_H\n\n#include <string>\nusing std::string;\n\n#include \"query_base.h\"\n#include \"queryresult.h\"\n#include \"textquery.h\"\n\nclass WordQuery:public Query_base\n{\n\tfriend class Query;\n\tWordQuery(const string &s) :query_word(s){ }\n\tQueryResult eval(const TextQuery &t) const{ return t.query(query_word); }\n\tstring rep() const { return query_word; }\n\n\tstring query_word;\n};\n\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/andquery.cpp",
    "content": "#include \"andquery.h\"\n\n#include <algorithm>\nusing std::set_intersection;\n\n#include <iterator>\nusing std::inserter;\n\n#include <memory>\nusing std::make_shared;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n\nQueryResult\nAndQuery::eval(const TextQuery& text) const\n{\n\tauto left = lhs.eval(text);\n\tauto right = rhs.eval(text);\n\n\tauto ret_lines = make_shared<set<line_no>>();\n\n\tset_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));\n\n\treturn QueryResult(rep(), ret_lines, left.get_file());\n}\n"
  },
  {
    "path": "ch15/ex15.42_c/andquery.h",
    "content": "#ifndef _ANDQUERY_H\n#define _ANDQUERY_H\n\n#include <memory>\nusing std::shared_ptr;\n\n#include \"query.h\"\n#include \"binaryquery.h\"\n\nclass QueryResult;\nclass TextQuery;\n\nclass AndQuery :public BinaryQuery\n{\n\tfriend Query operator&(const Query&, const Query&);\n\tAndQuery(const Query &left, const Query &right) :BinaryQuery(left, right, \"&\"){ }\n\tQueryResult eval(const TextQuery&) const;\n};\n\ninline Query operator&(const Query &lhs, const Query &rhs)\n{\n\treturn shared_ptr<Query_base>(new AndQuery(lhs, rhs));\n}\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/binaryquery.cpp",
    "content": "#include \"binaryquery.h\"\n"
  },
  {
    "path": "ch15/ex15.42_c/binaryquery.h",
    "content": "#ifndef _BINARYQUERY_H\n#define _BINARYQUERY_H\n\n#include <string>\nusing std::string;\n\n#include \"query.h\"\n#include \"query_base.h\"\n\n\nclass BinaryQuery :public Query_base\n{\nprotected:\n\tBinaryQuery(const Query &l, const Query &r, string s) :lhs(l), rhs(r), opSym(s){ }\n\tstring rep() const\n\t{\n\t\treturn \"(\" + lhs.rep() + \" \" + opSym + \" \" + rhs.rep() + \")\";\n\t}\n\n\tQuery lhs, rhs;\n\tstring opSym;\n};\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/main.cpp",
    "content": "#include <iostream>\nusing std::cout; using std::cin; using std::endl;\n\n#include <fstream>\nusing std::ifstream;\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n#include \"andquery.h\"\n#include \"orquery.h\"\n#include \"notquery.h\"\n\nint main()\n{\n    ifstream fin(\"test.txt\");\n\tTextQuery text(fin);\n\tauto q = ~Query(\"Alice\");\n\t\n\tauto result = q.eval(text);\n\tprint(cout, result);\n\tcout << endl;\n\tprint(cout, result, -3, 5);\n\tcout << endl;\n\tprint(cout, result, 3, 5);\n\tcout << endl;\n\tprint(cout, result, 3, 20);\n\tcout << endl;\n\t\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.42_c/notquery.cpp",
    "content": "#include \"notquery.h\"\n\n#include <memory>\nusing std::make_shared;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n\n\nQueryResult\nNotQuery::eval(const TextQuery &text) const\n{\n\tauto result = query.eval(text);\n\n\tauto ret_lines = make_shared<set<line_no>>();\n\n\tauto beg = result.begin();\n\tauto end = result.end();\n\n\tauto sz = result.get_file()->size();\n\tfor (size_t n = 0; n != sz; ++n)\n\t{\n\t\tif (beg == end || *beg != n)\n\t\t\tret_lines->insert(n);\n\t\telse if (beg != end)\n\t\t\t++beg;\n\t}\n\treturn QueryResult(rep(), ret_lines, result.get_file());\n}\n"
  },
  {
    "path": "ch15/ex15.42_c/notquery.h",
    "content": "#ifndef _NOTQUERY_H\n#define _NOTQUERY_H\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <string>\nusing std::string;\n\n#include \"query.h\"\n#include \"query_base.h\"\n\nclass QueryResult;\nclass TextQuery;\n\nclass NotQuery :public Query_base\n{\n\tfriend Query operator~(const Query&);\n\t//call Query's default copy constructor.\n\tNotQuery(const Query &q) :query(q){ }\n\tstring rep() const{ return \"~(\" + query.rep() + \")\"; }\n\tQueryResult eval(const TextQuery&) const;\n\n\tQuery query;\n};\n\ninline Query operator~(const Query &operand)\n{\n\treturn shared_ptr<Query_base>(new NotQuery(operand));\n}\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/orquery.cpp",
    "content": "#include \"orquery.h\"\n\n#include <memory>\nusing std::make_shared;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n#include \"textquery.h\"\n#include \"query.h\"\n\nQueryResult\nOrQuery::eval(const TextQuery &text) const\n{\n\tauto right = rhs.eval(text);\n\tauto left = lhs.eval(text);\n\tauto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());\n\tret_lines->insert(right.begin(), right.end());\n\treturn QueryResult(rep(), ret_lines, left.get_file());\n}\n"
  },
  {
    "path": "ch15/ex15.42_c/orquery.h",
    "content": "#ifndef _ORQUERY_H\n#define _ORQUERY_H\n\n#include <memory>\nusing std::shared_ptr;\n\n#include \"query.h\"\n#include \"binaryquery.h\"\n\nclass QueryResult;\nclass TextQuery;\n\nclass OrQuery :public BinaryQuery\n{\n\tfriend Query operator|(const Query&, const Query&);\n\tOrQuery(const Query &left, const Query &right) :BinaryQuery(left, right, \"|\"){ }\n\tQueryResult eval(const TextQuery&) const;\n};\n\ninline Query operator|(const Query &lhs, const Query &rhs)\n{\n\treturn shared_ptr<Query_base>(new OrQuery(lhs, rhs));\n}\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/query.cpp",
    "content": "#include \"query.h\"\n\n#include <ostream>\nusing std::ostream;\n\nostream&\noperator<<(ostream &os, const Query &query)\n{\n\treturn os << query.rep();\n}\n"
  },
  {
    "path": "ch15/ex15.42_c/query.h",
    "content": "#ifndef _QUERY_H\n#define _QUERY_H\n\n#include <ostream>\nusing std::ostream;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <string>\nusing std::string;\n\n#include \"query_base.h\"\n#include \"queryresult.h\"\n#include \"wordquery.h\"\n\n\nclass TextQuery;\n\nclass Query\n{\n\tfriend Query operator~(const Query&);\n\tfriend Query operator|(const Query&, const Query&);\n\tfriend Query operator&(const Query&, const Query&);\npublic:\n\tQuery(const string&);\n\t//call QueryResult's default copy constructor.\n\tQueryResult eval(const TextQuery &t) const { return q->eval(t); }\n\tstring rep() const { return q->rep(); }\nprivate:\n\tQuery(shared_ptr<Query_base> query) :q(query){ }\n\tshared_ptr<Query_base> q;\n};\n\nostream & operator<<(ostream &os, const Query &query);\n\ninline Query::Query(const string &s) :q(new WordQuery(s)){ }\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/query_base.cpp",
    "content": "#include \"query_base.h\"\n"
  },
  {
    "path": "ch15/ex15.42_c/query_base.h",
    "content": "#ifndef _QUERY_BASE_H\n#define _QUERY_BASE_H\n\n#include <string>\nusing std::string;\n\n#include \"textquery.h\"\n\nclass Query_base\n{\n\tfriend class Query;\nprotected:\n\tusing line_no = TextQuery::line_no;\n\tvirtual ~Query_base() = default;\nprivate:\n\tvirtual QueryResult eval(const TextQuery&) const = 0;\n\tvirtual string rep() const = 0;\n};\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/queryresult.cpp",
    "content": "#include \"queryresult.h\"\n\n#include <iostream>\nusing std::ostream;\n\nostream&\nprint(ostream &os, const QueryResult &qr)\n{\n    os <<\"The result of your query \"<< qr.sought <<\" is: \\n\";\n    for (const auto &index: *qr.lines)\n        os << \"\\t(line \" << index + 1 << \")\"\n           << *(qr.file->begin() + index) << \"\\n\";\n    return os;\n}\n\n/*\nHead is the first line of the range.\nTrail is the last line of the range.\n*/\nostream&\nprint(ostream& os, const QueryResult &qr, size_t head, size_t trail)\n{\n\tif (head > trail)\n\t{\n\t\tos << \"illegal range!\\n\";\n\t\treturn os;\n\t}\n\telse\n\t{\n\t\tos << \"The result of your query \" << qr.sought << \" is: \\n\";\n\t\tfor (const auto &index : *qr.lines)\n\t\t{\n\t\t\tif (index + 1 >= head&&index + 1 <= trail)\n\t\t\t{\n\t\t\t\tos << \"\\t(line \" << index + 1 << \")\"\n\t\t\t\t\t<< *(qr.file->begin() + index) << \"\\n\";\n\t\t\t}\n\t\t}\n\t\treturn os;\n\t}\n}\n"
  },
  {
    "path": "ch15/ex15.42_c/queryresult.h",
    "content": "#ifndef _QUERYRESULT_H\n#define _QUERYRESULT_H\n\n#include <iostream>\nusing std::ostream;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <set>\nusing std::set;\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include \"textquery.h\"\n\n\nclass QueryResult\n{\n    friend ostream& print(ostream&, const QueryResult&);\n\tfriend ostream& print(ostream&, const QueryResult&, \n\t\tsize_t, size_t);\npublic:\n\tQueryResult(string s,\n\t\tshared_ptr<set<TextQuery::line_no>> l,\n\t\tshared_ptr<vector<string>> f) :\n\t\tsought(s), lines(l), file(f){ }\n\n\tset<TextQuery::line_no>::iterator begin(){ return lines->begin(); }\n\tset<TextQuery::line_no>::iterator end(){ return lines->end(); }\n\tshared_ptr<vector<string>> get_file(){ return file; }\n\nprivate:\n    string sought;\n    shared_ptr<set<TextQuery::line_no>> lines;\n    shared_ptr<vector<string>> file;\n\n\tTextQuery::line_no line_no() const { return lines->size(); }\n};\n\nostream&\nprint(ostream&, const QueryResult&);\n\nostream&\nprint(ostream&, const QueryResult&, size_t, size_t);\n#endif \n"
  },
  {
    "path": "ch15/ex15.42_c/test.txt",
    "content": "Alice Emma has long flowing red hair.\nHer Daddy says when the wind blows\nthrough her hair, it looks almost alive,\nlike a fiery bird in flight.\nA beautiful fiery bird, he tells her,\nmagical but untamed.\n\"Daddy, shush, there is no such thing,\"\nshe tells him, at the same time wanting\nhim to tell her more.\nShyly, she asks, \"I mean, Daddy, is there?\""
  },
  {
    "path": "ch15/ex15.42_c/textquery.cpp",
    "content": "#include \"textquery.h\"\n\n#include <fstream>\nusing std::ifstream;\n\n#include <sstream>\nusing std::istringstream;\n\n#include <memory>\nusing std::shared_ptr; using std::make_shared;\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <map>\nusing std::map;\n\n#include <set>\nusing std::set;\n\n#include \"queryresult.h\"\n\n\nTextQuery::TextQuery(ifstream& is) :file(new vector<string>)\n{\n\tusing std::getline;\n\n\tstring text;\n    while(getline(is, text))\n    {\n        file->push_back(text);\n\t\tint n = file->size() - 1;\n\t\tistringstream line(text);\n        string word;\n        while(line >> word)\n        {\n\t\t\tauto p = handlePunct(word);\n\t\t\tfor (auto w : *p)\n\t\t\t{\n\t\t\t\tauto &lines = wm[w];\n\t\t\t\tif (!lines)\n\t\t\t\t\tlines.reset(new set<line_no>);\n\t\t\t\tlines->insert(n);\n\t\t\t}\n        }\n    }\n}\n\nQueryResult TextQuery::query(const string &sought) const\n{\n    static shared_ptr<set<line_no>> nodata(new set<line_no>);\n\n    // fetch the iterator to the matching element in the map<word, lines>.\n    //std::map<std::string, std::shared_ptr<std::set<line_no>>>::const_iterator\n    auto loc = wm.find(sought);\n    if(loc == wm.end())\n        return QueryResult(sought, nodata, file);\n    else\n        return QueryResult(sought, loc->second, file);\n}\n\nshared_ptr<vector<string>> TextQuery::handlePunct(const string &s)\n{\n\tshared_ptr<vector<string>> p =\n\t\tmake_shared<vector<string>>();\n\tsize_t first = 0, index = 0;\n\twhile(index != s.size())\n\t{\n\t\tif (ispunct(s[index]))\n\t\t{\n\t\t\tstring word = s.substr(first, index - first);\n\t\t\tif (!word.empty())\n\t\t\t\tp->push_back(word);\n\t\t\tp->push_back(s.substr(index, 1));\n\t\t\t++index;\n\t\t\tfirst = index;\n\t\t}\n\t\telse\n\t\t\t++index;\n\t}\n\tstring trail = s.substr(first);\n\tif (!trail.empty())\n\t\tp->push_back(trail);\n\n\treturn p;\n}\n"
  },
  {
    "path": "ch15/ex15.42_c/textquery.h",
    "content": "#ifndef _TEXTQUERY_H\n#define _TEXTQUERY_H\n\n#include <fstream>\nusing std::ifstream;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <vector>\nusing std::vector;\n\n#include <string>\nusing std::string;\n\n#include <map>\nusing std::map;\n\n#include <set>\nusing std::set;\n\nclass QueryResult;\n\nclass TextQuery\n{\n\npublic:\n    typedef vector<string>::size_type line_no;\n\n    TextQuery(ifstream&);\n    QueryResult query(const string&) const;\n\nprivate:\n    shared_ptr<vector<string>> file;\n\tmap<string, shared_ptr<set<line_no>>> wm;\n\n\tshared_ptr<vector<string>> handlePunct(const string&);\n};\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.42_c/wordquery.cpp",
    "content": "#include \"wordquery.h\"\n"
  },
  {
    "path": "ch15/ex15.42_c/wordquery.h",
    "content": "#ifndef _WORDQUERY_H\n#define _WORDQUERY_H\n\n#include <string>\nusing std::string;\n\n#include \"query_base.h\"\n#include \"queryresult.h\"\n#include \"textquery.h\"\n\nclass WordQuery:public Query_base\n{\n\tfriend class Query;\n\tWordQuery(const string &s) :query_word(s){ }\n\tQueryResult eval(const TextQuery &t) const{ return t.query(query_word); }\n\tstring rep() const { return query_word; }\n\n\tstring query_word;\n};\n\n\n#endif\n"
  },
  {
    "path": "ch15/ex15.7/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    return n * price * ( n >= min_qty ? 1 - discount : 1);\n}\n"
  },
  {
    "path": "ch15/ex15.7/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include <quote.h>\n\nclass Bulk_quote : public Quote\n{\npublic:\n    Bulk_quote() = default;\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Quote(b, p), min_qty(q), discount(disc)  {   }\n\n    double net_price(std::size_t n) const override;\n\nprivate:\n    std::size_t min_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.7/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\ndouble Limit_quote::net_price(std::size_t n) const\n{\n  if (n > max_qty)\n    return max_qty * price * discount + (n - max_qty) * price;\n  else\n    return n * discount *price;\n}\n"
  },
  {
    "path": "ch15/ex15.7/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"quote.h\"\n\nclass Limit_quote : public Quote\n{\npublic:\n    Limit_quote();\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Quote(b, p), max_qty(max), discount(disc)    {   }\n\n    double net_price(std::size_t n) const override;\n\nprivate:\n    std::size_t max_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.7/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       21  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.7:\n// Define a class that implements a limited discount strategy, which applies\n// a discount to books purchased up to a given limit. If the number of copies\n// exceeds that limit, the normal price applies to those purchased beyond the\n// limit.\n//\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n\ndouble print_total (std::ostream& os, const Quote& item, size_t n);\nint main()\n{\n    // ex15.6\n    Quote q(\"textbook\", 10.60);\n    Bulk_quote bq(\"textbook\", 10.60, 10, 0.3);\n    Limit_quote lq(\"Bible\", 10.60, 10 , 0.3);\n\n    print_total(std::cout, q, 5);\n    print_total(std::cout, bq, 5);\n    print_total(std::cout , lq, 5);\n\n    return 0;\n}\n\ndouble print_total(std::ostream &os, const Quote &item, size_t n)\n{\n    double ret = item.net_price(n);\n\n    os << \"ISBN:\" << item.isbn()\n       << \"# sold: \" << n << \" total due: \" << ret << std::endl;\n\n    return ret;\n}\n"
  },
  {
    "path": "ch15/ex15.7/quote.cpp",
    "content": "#include \"quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.7/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n\nclass Quote\n{\npublic:\n    Quote() = default;\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { return n * price; }\n\n    virtual ~Quote() = default;\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 0.0;\n\n};\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.8.9.10/ex15.8.9.10.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       21  Jan 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.8:\n// Define static type and dynamic type.\n//  The static type of an expression is always known at compile time.\n//  The dynamic type is the type of the object in memory that the variable or\n//  expression represents. The dynamic type may not be known until run time.\n//\n// Exercise 15.9:\n// When is it possible for an expression’s static type to differ from its\n// dynamic type? Give three examples in which the static and dynamic type differ.\n//  The static type of a pointer or reference to a base class may differ from\n//  its dynamic type. Anying like this can be an example\n//\n// Exercise 15.10:\n// Recalling the discussion from §8.1 (p. 311), explain how the program on\n// page 317 that passed an ifstream to the Sales_data read function works.\n//  the function takes a std::istream from which std::ifstream is derived.\n//  Hence the ifstream object \"is a\" istream , which is why it works.\n//\n\n#include <iostream>\n#include <string>\n#include <istream>\n#include <fstream>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n\ndouble print_total (std::ostream& os, const Quote& item, size_t n);\nint main()\n{\n    return 0;\n}\n\ndouble print_total(std::ostream &os, const Quote &item, size_t n)\n{\n    double ret = item.net_price(n);\n\n    os << \"ISBN:\" << item.isbn()\n       << \"# sold: \" << n << \" total due: \" << ret << std::endl;\n\n    return ret;\n}\n"
  },
  {
    "path": "ch15/ex15.9/bulk_quote.cpp",
    "content": "#include \"bulk_quote.h\"\n\ndouble Bulk_quote::net_price(std::size_t n) const\n{\n    std::cout << \"Bulk_Quote net_price method got called\" << std::endl;\n    return n * price * ( n >= min_qty ? 1 - discount : 1);\n}\n"
  },
  {
    "path": "ch15/ex15.9/bulk_quote.h",
    "content": "#ifndef BULK_QUOTE_H\n#define BULK_QUOTE_H\n#include \"quote.h\"\n\nclass Bulk_quote : public Quote\n{\npublic:\n    Bulk_quote() = default;\n    Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :\n        Quote(b, p), min_qty(q), discount(disc)  {   }\n\n    double net_price(std::size_t n) const override;\n\nprivate:\n    std::size_t min_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // BULK_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.9/limit_quote.cpp",
    "content": "#include \"limit_quote.h\"\n\ndouble Limit_quote::net_price(std::size_t n) const\n{\n  if (n > max_qty)\n    return max_qty * price * discount + (n - max_qty) * price;\n  else\n    return n * discount *price;\n}\n"
  },
  {
    "path": "ch15/ex15.9/limit_quote.h",
    "content": "#ifndef LIMIT_QUOTE_H\n#define LIMIT_QUOTE_H\n\n#include \"quote.h\"\n\nclass Limit_quote : public Quote\n{\npublic:\n    Limit_quote();\n    Limit_quote(const std::string& b, double p, std::size_t max, double disc):\n        Quote(b, p), max_qty(max), discount(disc)    {   }\n\n    double net_price(std::size_t n) const override;\n\nprivate:\n    std::size_t max_qty     = 0;\n    double      discount    = 0.0;\n};\n\n#endif // LIMIT_QUOTE_H\n"
  },
  {
    "path": "ch15/ex15.9/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Hoesel Markus\n *  @date       11  Apr 2016\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 15.9:\n// When is it possible for an expression’s static type to differ from its \n// dynamic type? Give three examples in which the static and dynamic type differ.\n//\n\n#include <iostream>\n#include <string>\n\n#include \"quote.h\"\n#include \"bulk_quote.h\"\n#include \"limit_quote.h\"\n\nint main()\n{\n    Bulk_quote bulk_quote(\"bulk_quote_1\", 10.10, 10, 0.5);\n\n    // The pointer is of static type Quote, but it's dynamic type is Bulk Quote\n    // Because of polymorphism the Bulk Quote implementation of the net_price()\n    // method gets called.\n    Quote *quote_pointer = &bulk_quote;\n    quote_pointer->net_price(5);\n\n    // The reference is of static type Quote, but it's dynamic type is Bulk Quote\n    // Like with the pointer, the Bulk Quote implementation of the net_price()\n    // method gets called.\n    Quote &quote_reference = bulk_quote;\n    quote_reference.net_price(5);\n\n    // The static type of this variable is Quote. Here the Bulk Quote object\n    // gets upcasted. The Quote part of bulk_quote gets copied into quote, but\n    // the rest is not handled. Because of the cast the Quote implementation of\n    // the net_price() method gets called.\n    Quote quote = bulk_quote;\n    quote.net_price(5);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch15/ex15.9/quote.cpp",
    "content": "#include \"quote.h\"\n\n"
  },
  {
    "path": "ch15/ex15.9/quote.h",
    "content": "#ifndef QUOTE_H\n#define QUOTE_H\n\n#include <string>\n#include <iostream>\n\nclass Quote\n{\npublic:\n    Quote() = default;\n    Quote(const std::string &b, double p) :\n        bookNo(b), price(p) { }\n\n    std::string     isbn() const { return bookNo; }\n    virtual double  net_price(std::size_t n) const { \n      std::cout << \"Quote net_price method got called\" << std::endl;\n      return n * price; \n    }\n\n    virtual ~Quote() = default;\n\nprivate:\n    std::string bookNo;\n\nprotected:\n    double  price = 0.0;\n\n};\n\n#endif // QUOTE_H\n"
  },
  {
    "path": "ch16/ex16.1.2.3/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.1:\n// Define instantiation.\n//  When the compiler instantiates a template, it creates a new “instance” of\n//  the template using the actual template argument(s) in place of the\n//  corresponding template parameter(s).\n//\n// Exercise 16.2:\n// Write and test your own versions of the compare functions.\n//\n// Exercise 16.3:\n// Call your compare function on two Sales_data objects to see how your compiler\n// handles errors during instantiation.\n//  error: no match for 'operator<' (operand types are 'const Sales_data' and\n//  'const Sales_data')\n//\n//\n//\n\n#include <iostream>\nusing std::cout;\nusing std::endl;\n\n#include <vector>\nusing std::vector;\n\nclass Sales_data{ };\n\ntemplate<typename T>\nint compare(const T& lhs, const T& rhs)\n{\n    if(lhs < rhs) return -1;\n    if(rhs < lhs) return  1;\n    return 0;\n}\n\nint main()\n{\n    // Test compare function\n    cout << compare(1, 0) << endl;\n    vector<int> vec1{ 1, 2, 3 }, vec2{ 4, 5, 6 };\n    cout << compare(vec1, vec2) << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.12.13/Blob.h",
    "content": "#ifndef BLOB_H\n#define BLOB_H\n#include <memory>\n#include <vector>\n\ntemplate<typename T> class Blob\n{\npublic:\n    typedef T value_type;\n    typedef typename std::vector<T>::size_type size_type;\n\n    // constructors\n    Blob();\n    Blob(std::initializer_list<T> il);\n\n    // number of elements in the Blob\n    size_type size() const { return data->size(); }\n    bool      empty() const{ return data->empty(); }\n\n    void push_back(const T& t) { data->push_back(t); }\n    void push_back(T&& t)      { data->push_back(std::move(t)); }\n    void pop_back();\n\n    // element access\n    T& back();\n    T& operator[](size_type i);\n\n    const T& back() const;\n    const T& operator [](size_type i) const;\n\nprivate:\n    std::shared_ptr<std::vector<T>> data;\n    // throw msg if data[i] isn't valid\n    void check(size_type i, const std::string &msg) const;\n};\n\n// constructors\ntemplate<typename T>\nBlob<T>::Blob() : data(std::make_shared<std::vector<T>>())\n{ }\n\ntemplate<typename T>\nBlob<T>::Blob(std::initializer_list<T> il):\n    data(std::make_shared<std::vector<T>>(il)){ }\n\ntemplate<typename T>\nvoid Blob<T>::check(size_type i, const std::string &msg) const\n{\n    if(i >= data->size())\n        throw std::out_of_range(msg);\n}\n\ntemplate<typename T>\nT& Blob<T>::back()\n{\n    check(0, \"back on empty Blob\");\n    return data->back();\n}\n\ntemplate<typename T>\nconst T& Blob<T>::back() const\n{\n    check(0, \"back on empty Blob\");\n    return data->back();\n}\n\n\ntemplate<typename T>\nT& Blob<T>::operator [](size_type i)\n{\n    // if i is too big, check function will throw, preventing access to a nonexistent element\n    check(i, \"subscript out of range\");\n    return (*data)[i];\n}\n\n\ntemplate<typename T>\nconst T& Blob<T>::operator [](size_type i) const\n{\n    // if i is too big, check function will throw, preventing access to a nonexistent element\n    check(i, \"subscript out of range\");\n    return (*data)[i];\n}\n\ntemplate<typename T>\nvoid Blob<T>::pop_back()\n{\n    check(0, \"pop_back on empty Blob\");\n    data->pop_back();\n}\n\n#endif // BLOB_H\n"
  },
  {
    "path": "ch16/ex16.12.13/blobptr.h",
    "content": "#ifndef BLOBPTR_H\n#define BLOBPTR_H\n\n#include \"Blob.h\"\n#include <memory>\n#include <vector>\n\ntemplate <typename> class BlobPtr;\n\ntemplate <typename T>\nbool operator ==(const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\ntemplate <typename T>\nbool operator < (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\n\ntemplate<typename T> class BlobPtr\n{\n    friend bool operator ==<T>\n    (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\n    friend bool operator < <T>\n    (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\npublic:\n    BlobPtr() : curr(0) { }\n    BlobPtr(Blob<T>& a, std::size_t sz = 0) :\n        wptr(a.data), curr(sz) { }\n\n    T& operator*() const\n    {\n        auto p = check(curr, \"dereference past end\");\n        return (*p)[curr];\n    }\n\n    // prefix\n    BlobPtr& operator++();\n    BlobPtr& operator--();\n\n    // postfix\n    BlobPtr operator ++(int);\n    BlobPtr operator --(int);\n\nprivate:\n    // returns  a shared_ptr to the vector if the check succeeds\n    std::shared_ptr<std::vector<T>>\n         check(std::size_t, const std::string&) const;\n\n    std::weak_ptr<std::vector<T>> wptr;\n    std::size_t curr;\n\n};\n\n// prefix ++\ntemplate<typename T>\nBlobPtr<T>& BlobPtr<T>::operator ++()\n{\n    // if curr already points past the end of the container, can't increment it\n    check(curr, \"increment past end of StrBlob\");\n    ++curr;\n    return *this;\n}\n\n// prefix --\ntemplate<typename T>\nBlobPtr<T>& BlobPtr<T>::operator --()\n{\n    -- curr;\n    check(curr, \"decrement past begin of BlobPtr\");\n\n    return *this;\n}\n\n\n// postfix ++\ntemplate<typename T>\nBlobPtr<T> BlobPtr<T>::operator ++(int)\n{\n    BlobPtr ret = *this;\n    ++*this;\n\n    return ret;\n}\n\n// postfix --\ntemplate<typename T>\nBlobPtr<T> BlobPtr<T>::operator --(int)\n{\n    BlobPtr ret = *this;\n    --*this;\n\n    return ret;\n}\n\ntemplate<typename T> bool operator==(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {\n    if (lhs.wptr.lock() != rhs.wptr.lock()) {\n\t\tthrow runtime_error(\"ptrs to different Blobs!\");\n\t}\n\treturn lhs.i == rhs.i;\n}\n\ntemplate<typename T> bool operator< (const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {\n\tif (lhs.wptr.lock() != rhs.wptr.lock()) {\n\t\tthrow runtime_error(\"ptrs to different Blobs!\");\n\t}\n\treturn lhs.i < rhs.i;\n}\n\n#endif // BLOBPTR_H\n"
  },
  {
    "path": "ch16/ex16.12.13/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.12:\n// Write your own version of the Blob and BlobPtr templates. including the\n// various const members that were not shown in the text.\n//\n// Exercise 16.13:\n// Explain which kind of friendship you chose for the equality and relational\n// operators for BlobPtr.\n//  As shown in the class body.\n//\n\n\n#include <iostream>\n#include <vector>\n#include <list>\n#include <string>\n#include \"Blob.h\"\n#include \"blobptr.h\"\n\nint main()\n{\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.14.15/Screen.h",
    "content": "//\n// Exercise 16.14:\n// Write a Screen class template that uses nontype parameters to define the\n// height and width of the Screen.\n//\n\n#ifndef SCREEN_H\n#define SCREEN_H\n\n#include <string>\n#include <iostream>\n\ntemplate<unsigned H, unsigned W>\nclass Screen {\npublic:\n    typedef std::string::size_type pos;\n    Screen() = default; // needed because Screen has another constructor\n    // cursor initialized to 0 by its in-class initializer\n    Screen(char c):contents(H * W, c) { }\n    char get() const              // get the character at the cursor\n        { return contents[cursor]; }       // implicitly inline\n    Screen &move(pos r, pos c);      // can be made inline later\n\n    friend std::ostream & operator<< ( std::ostream &os , const Screen<H, W> & c ) \n    {\n        unsigned int i, j;\n        for( i=0 ;i<c.height; i++ )\n        {\n                os<<c.contents.substr(0, W)<<std::endl;\n        }\n        return os;\n    }\n\n    friend std::istream & operator>> ( std::istream &is , Screen &  c )\n    {\n            char a;\n            is>>a;\n            std::string temp(H*W, a);\n            c.contents = temp;\n            return is;\n    }\nprivate:\n    pos cursor = 0;\n    pos height = H, width = W;\n    std::string contents;\n};\n\ntemplate<unsigned H, unsigned W>\ninline Screen<H, W>& Screen<H, W>::move(pos r, pos c)\n{\n    pos row = r * width;\n    cursor = row + c;\n    return *this;\n}\n#endif // SCREEN_H\n"
  },
  {
    "path": "ch16/ex16.14.15/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.14:\n// Write a Screen class template that uses nontype parameters to define the\n// height and width of the Screen.\n//\n// Exercise 16.15:\n// Implement input and output operators for your Screen template.\n// Which, if any, friends are necessary in class Screen to make the input and\n// output operators work? Explain why each friend declaration, if any, was\n// needed.\n//    According to  the chapter of 14.2.1, the class of << and <<  should be a friend of this class.\n//\n\n#include \"Screen.h\"\n#include <iostream>\n\nint main()\n{\n    Screen<5, 5> scr('c');\n    Screen<5, 5> scr2;\n\n    // output src to the screen\n    std::cout<<scr;\n    // input connet  to the  src \n    std::cin>>scr2;\n    // test input\n    std::cout<<scr2;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.16/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.16:\n// Rewrite the StrVec class (§ 13.5, p. 526) as a template named Vec.\n//\n\n#include \"vec.h\"\n#include <vector>\n#include <iostream>\n\nint main()\n{\n    Vec<int> v = { 1, 2, 3, 4, 5 };\n\n    Vec<int> v2;\n\n    v2 = v;\n    std::cout << v2.capacity() << \"\\n\";\n    v2.push_back(99);\n    v2.resize(2, 2);\n\n    for (auto t : v2)\n        std::cout << t << \" \";\n\n\n    std::cout << v2.capacity() << \"\\n\";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.16/vec.h",
    "content": "/***************************************************************************\n *  @file       vec.h\n *  @author     Alan.W\n *  @date       02  FEB 2014\n *  @remark\n ***************************************************************************/\n\n#ifndef VEC_H\n#define VEC_H\n\n#include <memory>\n\n/**\n *  @brief a vector like class\n */\ntemplate<typename T>\nclass Vec\n{\npublic:\n    Vec():element(nullptr), first_free(nullptr), cap(nullptr){ }\n    Vec(std::initializer_list<T> l);\n    Vec(const Vec& v);\n\n    Vec& operator =(const Vec& rhs);\n\n    ~Vec();\n\n    // memmbers\n    void push_back(const T& t);\n\n    std::size_t size() const    { return first_free - element; }\n    std::size_t capacity()const { return cap - element; }\n\n    T* begin() const { return element;      }\n    T* end()   const { return first_free;   }\n\n    void reserve(std::size_t n);\n\n    void resize(std::size_t n);\n    void resize(std::size_t n, const T& t);\n\nprivate:\n    // data members\n    T* element;\n    T* first_free;\n    T* cap;\n\n    std::allocator<T> alloc;\n\n    // utillities\n    void reallocate();\n    void chk_n_alloc()  { if(size()==capacity()) reallocate(); }\n    void free();\n\n    void wy_alloc_n_move(std::size_t n);\n\n    std::pair<T*, T*> alloc_n_copy(T* b, T* e);\n};\n\n\n// copy constructor\ntemplate<typename T>\nVec<T>::Vec(const Vec &v)\n{\n    /**\n     * @brief newData is a pair of pointers pointing to newly allocated and copied\n     *        from range : [b, e)\n     */\n    std::pair<T*, T*> newData = alloc_n_copy(v.begin(), v.end());\n\n    element = newData.first;\n    first_free = cap = newData.second;\n}\n\n\n// constructor that takes initializer_list<T>\ntemplate<typename T>\nVec<T>::Vec(std::initializer_list<T> l)\n{\n    // allocate memory as large as l.size()\n    T* const newData = alloc.allocate(l.size());\n\n    // copy elements from l to the address allocated\n    T* p = newData;\n    for(const auto &t : l)\n        alloc.construct(p++, t);\n\n    // build data structure\n    element = newData;\n    first_free = cap = element + l.size();\n}\n\n\n// operator =\ntemplate<typename T>\nVec<T>& Vec<T>::operator =(const Vec& rhs)\n{\n    // allocate and copy first to protect against self_assignment\n    std::pair<T*, T*> newData = alloc_n_copy(rhs.begin(), rhs.end());\n\n    // destroy and deallocate\n    free();\n\n    // update data structure\n    element = newData.first;\n    first_free = cap = newData.second;\n\n    return *this;\n}\n\n\n// destructor\ntemplate<typename T>\nVec<T>::~Vec()\n{\n    free();\n}\n\n\n\n/**\n * @brief   allocate new memeory if nessary and push back the new T\n * @param t new T\n */\ntemplate<typename T>\nvoid Vec<T>::push_back(const T &t)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, t);\n}\n\n\n\n/**\n * @brief   preallocate enough memory for specified number of elements\n * @param n number of elements required\n */\ntemplate<typename T>\nvoid Vec<T>::reserve(std::size_t n)\n{\n    // if n too small, just return without doing anything\n    if(n <= capacity()) return;\n\n    // allocate new memory and move data from old address to the new one\n    wy_alloc_n_move(n);\n}\n\n\n/**\n *  @brief  Resizes to the specified number of elements.\n *  @param  n  Number of elements the %vector should contain.\n *\n *  This function will resize it to the specified\n *  number of elements.  If the number is smaller than the\n *  current size it is truncated, otherwise\n *  default constructed elements are appended.\n */\ntemplate<typename T>\nvoid Vec<T>::resize(std::size_t n)\n{\n    resize(n, T());\n}\n\n\n\n/**\n *  @brief  Resizes it to the specified number of elements.\n *  @param  __new_size  Number of elements it should contain.\n *  @param  __x  Data with which new elements should be populated.\n *\n *  This function will resize it to the specified\n *  number of elements.  If the number is smaller than the\n *  current size the it is truncated, otherwise\n *  the it is extended and new elements are populated with\n *  given data.\n */\ntemplate<typename T>\nvoid Vec<T>::resize(std::size_t n, const T &t)\n{\n    if(n < size())\n    {\n        // destroy the range [element+n, first_free) using destructor\n        for(auto p = element + n; p != first_free;   )\n            alloc.destroy(p++);\n        // update first_free to point to the new address\n        first_free = element + n;\n    }\n    else if(n > size())\n    {\n        for (auto i = size(); i != n; ++i)\n            push_back(t);\n    }\n}\n\n\n/**\n * @brief   allocate new space for the given range and copy them into it\n * @param b\n * @param e\n * @return  a pair of pointers pointing to [first element , one past the last) in the new space\n */\ntemplate<typename T>\nstd::pair<T*, T*>\nVec<T>::alloc_n_copy(T *b, T *e)\n{\n    // calculate the size needed and allocate space accordingly\n    T* data = alloc.allocate(e-b);\n    return { data, std::uninitialized_copy(b, e, data) };\n    //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // which copies the range[first, last) to the space to which\n    // the starting address data is pointing.\n    // This function returns a pointer to one past the last element\n}\n\n\n/**\n * @brief   destroy the elements and deallocate the space previously allocated.\n */\ntemplate<typename T>\nvoid Vec<T>::free()\n{\n    // if not nullptr\n    if(element)\n    {\n        // destroy it in reverse order.\n        for(auto p = first_free; p != element;    )\n            alloc.destroy(--p);\n\n        alloc.deallocate(element, capacity());\n    }\n}\n\n\n/**\n * @brief   allocate memory for spicified number of elements\n * @param n\n * @note    it's user's responsibility to ensure that @param n is greater than\n *          the current capacity.\n */\ntemplate<typename T>\nvoid Vec<T>::wy_alloc_n_move(std::size_t n)\n{\n    // allocate as required.\n    std::size_t newCapacity = n;\n    T* newData = alloc.allocate(newCapacity);\n\n    // move the data from old place to the new one\n    T* dest = newData;\n    T* old  = element;\n    for(std::size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*old++));\n\n    free();\n\n    // update data structure\n    element     =   newData;\n    first_free  =   dest;\n    cap         =   element + newCapacity;\n}\n\n\n/**\n * @brief   Double the capacity and using std::move move the original data to the newly\n *          allocated memory\n */\ntemplate<typename T>\nvoid Vec<T>::reallocate()\n{\n    // calculate the new capacity required\n    std::size_t newCapacity = size() ? 2 * size() : 1;\n\n    // allocate and move old data to the new space\n    wy_alloc_n_move(newCapacity);\n}\n\n\n\n#endif // VEC_H\n"
  },
  {
    "path": "ch16/ex16.17.18/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.17:\n// What, if any, are the differences between a type parameter that is declared\n// as a typename and one that is declared as a class? When must typename be used?\n//\n//  There is no difference. typename and class are interchangeable in the\n//  declaration of a type template parameter.\n//  You do, however, have to use class (and not typename) when declaring a\n//  template template parameter.\n//\n//  When we want to inform the compiler that a name represents a type, we must use\n//  the keyword typename, not class\n//\n// Exercise 16.18:\n// Explain each of the following function template declarations and identify\n// whether any are illegal. Correct each error that you find.\n//\n\ntemplate <typename T, typename U, typename V> void f1(T, U, V);\n//                   ^^^^^^^^ added to fix the error\n\ntemplate <typename T> T f2(T&);\n//                        ^^\n\ntemplate <typename T> inline T foo(T, unsigned int*);\n//                   ^^^^^^ inline must be after template\n\ntemplate <typename T> T f4(T, T);\n//                   ^ -- return type must be provided\n\ntypedef char Ctype;\n//          ^^^^^\n//the template declatation below hides this typedef\ntemplate <typename Ctype> Ctype f5(Ctype a);\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.19.20/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       03  Feb 2014\n *              Aug 2015       \n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.19:\n// Write a function that takes a reference to a container and prints the\n// elements in that container. Use the container’s size_type and size members\n// to control the loop that prints the elements.\n//\n// Exercise 16.20:\n// Rewrite the function from the previous exercise to use iterators returned\n// from begin and end to control the loop.\n//\n\n#include <iostream>\n#include <vector>\n#include <list>\n\n// ex16.19\ntemplate<typename Container>\nstd::ostream& print(Container const& container, std::ostream& os)\n{\n    for(typename Container::size_type i = 0; i != container.size(); ++ i)\n        os << container[i] << \" \";\n    return os;\n}\n\n// ex16.20\ntemplate<typename Container>\nstd::ostream& print2(Container const& container, std::ostream &os)\n{\n    for(auto curr = container.cbegin(); curr != container.cend(); ++curr)\n        os << *curr << \" \";\n    return os;\n}\n\n\nint main()\n{\n    std::vector<int> v = { 1, 23, 6, 4, 5, 7, 4 };\n    std::list<std::string> l = { \"ss\", \"sszz\", \"saaas\", \"s333s\", \"ss2\",\" sss\" };\n    print2(v, std::cout) << std::endl;\n    print2(l, std::cout) << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.21.22/DebugDelete.h",
    "content": "#ifndef DEBUGDELETE_H\n#define DEBUGDELETE_H\n\n#include <iostream>\n\nclass DebugDelete\n{\npublic:\n    DebugDelete(std::ostream& s = std::cerr) : os(s) { }\n    template<typename T>\n    void operator() (T* p) const\n    {\n        os << \"deleting unique_ptr\" << std::endl;\n        delete p;\n    }\n\nprivate:\n    std::ostream& os;\n};\n#endif // DEBUGDELETE_H\n"
  },
  {
    "path": "ch16/ex16.21.22/StrBlob.h",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced. Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n * \tPearson Education, Inc.\n * \tRights and Permissions Department\n * \tOne Lake Street\n * \tUpper Saddle River, NJ  07458\n * \tFax: (201) 236-3290\n*/\n\n#ifndef STRBLOB_H\n#define STRBLOB_H\n\n#include <vector>\n#include <string>\n#include <initializer_list>\n#include <memory>\n#include <stdexcept>\n\n// forward declaration needed for friend declaration in StrBlob\nclass StrBlobPtr;\n\nclass StrBlob\n{\n\tfriend class StrBlobPtr;\npublic:\n    typedef std::vector<std::string>::size_type size_type;\n\n\t// constructors\n    StrBlob() : data(std::make_shared<std::vector<std::string>>()) { }\n    StrBlob(std::initializer_list<std::string> il);\n\n\t// size operations\n    size_type size() const { return data->size(); }\n    bool empty() const { return data->empty(); }\n\n    // add and remove elements\n    void push_back(const std::string &t) { data->push_back(t); }\n    void pop_back();\n\n    // element access\n    std::string& front();\n    std::string& back();\n\n\t// interface to StrBlobPtr\n\tStrBlobPtr begin();  // can't be defined until StrBlobPtr is\n    StrBlobPtr end();\nprivate:\n    std::shared_ptr<std::vector<std::string>> data; \n    // throws msg if data[i] isn't valid\n    void check(size_type i, const std::string &msg) const;\n};\n\n// constructor\ninline\nStrBlob::StrBlob(std::initializer_list<std::string> il): \n              data(std::make_shared<std::vector<std::string>>(il)) { }\n\n// StrBlobPtr throws an exception on attempts to access a nonexistent element \nclass StrBlobPtr\n{\n\tfriend bool eq(const StrBlobPtr&, const StrBlobPtr&);\npublic:\n    StrBlobPtr(): curr(0) { }\n    StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }\n\n    // newly overloaded why?\n    StrBlobPtr(const StrBlob &a, const size_t sz = 0) : wptr(a.data), curr(sz) { }\n\n    std::string& deref() const;\n    StrBlobPtr& incr();       // prefix version\n    StrBlobPtr& decr();       // prefix version\nprivate:\n    // check returns a shared_ptr to the vector if the check succeeds\n    std::shared_ptr<std::vector<std::string>> \n        check(std::size_t, const std::string&) const;\n\n    // store a weak_ptr, which means the underlying vector might be destroyed\n    std::weak_ptr<std::vector<std::string>> wptr;  \n    std::size_t curr;      // current position within the array\n};\n\ninline\nstd::string& StrBlobPtr::deref() const\n{\n    auto p = check(curr, \"dereference past end\"); \n    return (*p)[curr];  // (*p) is the vector to which this object points\n}\n\ninline\nstd::shared_ptr<std::vector<std::string>> \nStrBlobPtr::check(std::size_t i, const std::string &msg) const\n{\n    auto ret = wptr.lock();   // is the vector still around?\n    if (!ret)\n        throw std::runtime_error(\"unbound StrBlobPtr\");\n\n    if (i >= ret->size()) \n        throw std::out_of_range(msg);\n    return ret; // otherwise, return a shared_ptr to the vector\n}\n\n// prefix: return a reference to the incremented object\ninline\nStrBlobPtr& StrBlobPtr::incr()\n{\n    // if curr already points past the end of the container, can't increment it\n    check(curr, \"increment past end of StrBlobPtr\");\n    ++curr;       // advance the current state\n    return *this;\n}\n\ninline\nStrBlobPtr& StrBlobPtr::decr()\n{\n    // if curr is zero, decrementing it will yield an invalid subscript\n    --curr;       // move the current state back one element}\n    check(-1, \"decrement past begin of StrBlobPtr\");\n    return *this;\n}\n\n// begin and end members for StrBlob\ninline\nStrBlobPtr\nStrBlob::begin() \n{\n\treturn StrBlobPtr(*this);\n}\n\ninline\nStrBlobPtr\nStrBlob::end() \n{\n\tauto ret = StrBlobPtr(*this, data->size());\n    return ret; \n}\n\n// named equality operators for StrBlobPtr\ninline\nbool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n\tauto l = lhs.wptr.lock(), r = rhs.wptr.lock();\n\t// if the underlying vector is the same \n\tif (l == r) \n\t\t// then they're equal if they're both null or \n\t\t// if they point to the same element\n\t\treturn (!r || lhs.curr == rhs.curr);\n\telse\n\t\treturn false; // if they point to difference vectors, they're not equal\n}\n\ninline\nbool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)\n{\n\treturn !eq(lhs, rhs); \n}\n#endif\n"
  },
  {
    "path": "ch16/ex16.21.22/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       03  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.21:\n// Write your own version of DebugDelete.\n//\n// Exercise 16.22:\n// Revise your TextQuery programs from § 12.3 (p. 484) so that the shared_ptr\n// members use a DebugDelete as their deleter (§ 12.1.4, p. 468).\n//\n\n#include <iostream>\n#include <vector>\n#include <list>\n\n#include \"DebugDelete.h\"\n#include <memory>\n\n#include \"wy_queryresult.h\"\n#include \"wy_textquery.h\"\n\nint main()\n{\n\n\n\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.21.22/wy_queryresult.cpp",
    "content": "/***************************************************************************\n *  @file       wy_queryresult.cpp\n *  @author     Alan.W\n *  @date       27  DEC 2013\n *  @remark\n ***************************************************************************/\n//\n// Exercise 12.27:\n// The TextQuery and QueryResult classes use only capabilities that we have\n// already covered. Without looking ahead, write your own versions of these\n// classes.\n//\n\n\n#include \"wy_queryresult.h\"\n\n// copy constructor\ninline wy_queryResult::wy_queryResult(const wy_queryResult &qr):\n    counter(qr.getCounter()), queryWord(qr.getQueryWord()),\n    sp_file(qr.getSp_file()), sp_Qmap(qr.getSp_Qmap())\n{\n}\n\n// constructor\nwy_queryResult::wy_queryResult(std::size_t c, const std::string &str,\n                               const wy_textQuery::sp_file_Tp &sp_f,\n                               const wy_textQuery::sp_Qmap_Tp &sp_m) :\n    counter(c), queryWord(str), sp_file(sp_f), sp_Qmap(sp_m)\n{\n}\n\n// a non-member function printing the result of a query.\nvoid print(std::ostream &os, const wy_queryResult &qr)\n{\n    // fetch the word being queried.\n    const std::string queryWord = qr.getQueryWord();\n\n    // print the word and occurrence times\n    os << \"The word [\"\n         <<queryWord\n           <<\"] occurs \"\n             <<qr.getCounter()\n               <<\" times :\\n\";\n\n    // fetch smart pointers to the map and the file\n    auto sp_m = qr.getSp_Qmap();\n    auto sp_f = qr.getSp_file();\n\n    // print each line in which it appears and the corresponding index.\n    for(const auto &index : (*sp_m)[queryWord])\n        std::cout << \"\\n(Line \"\n                    <<index\n                       <<\") \"\n                          << (*sp_f)[index]\n                             << \"\\n\\n\";\n}\n"
  },
  {
    "path": "ch16/ex16.21.22/wy_queryresult.h",
    "content": "/***************************************************************************\n *  @file       wy_queryresult.h\n *  @author     Alan.W\n *  @date       27  DEC 2013\n *  @remark\n ***************************************************************************/\n\n//\n// Exercise 12.27:\n// The TextQuery and QueryResult classes use only capabilities that we have\n// already covered. Without looking ahead, write your own versions of these\n// classes.\n//\n\n\n#ifndef WY_QUERYRESULT_H\n#define WY_QUERYRESULT_H\n#include <wy_textquery.h>\n\nclass wy_queryResult\n{\npublic:\n    // default constructor\n    wy_queryResult() = default;\n\n    // copy constructor\n    wy_queryResult(const wy_queryResult &qr);\n\n    wy_queryResult(std::size_t c, const std::string &str,\n                   const wy_textQuery::sp_file_Tp &sp_f,\n                   const wy_textQuery::sp_Qmap_Tp &sp_m);\n\n    std::size_t\n    getCounter() const { return counter; }\n\n    std::string\n    getQueryWord() const { return queryWord; }\n\n    wy_textQuery::sp_file_Tp\n    getSp_file() const { return sp_file; }\n\n    wy_textQuery::sp_Qmap_Tp\n    getSp_Qmap() const { return sp_Qmap; }\n\nprivate:\n\n    // number of occurrence\n    std::size_t counter = 0;\n\n    // the word being searched\n    std::string queryWord = \"\";\n\n    // smart pointer to a vector to be storing a file.\n    wy_textQuery::sp_file_Tp sp_file = nullptr;\n\n    // smart pointer to a map to be storing results of querries.\n    wy_textQuery::sp_Qmap_Tp sp_Qmap = nullptr;\n};\n\n// print the result of searching\nvoid print(std::ostream &os, const wy_queryResult &qr);\n\n#endif // WY_QUERYRESULT_H\n"
  },
  {
    "path": "ch16/ex16.21.22/wy_textquery.cpp",
    "content": "/***************************************************************************\n *  @file       wy_textquery.cpp\n *  @author     Alan.W\n *  @date       27  DEC 2013\n *  @remark     03  FEB 2014    deleter added\n ***************************************************************************/\n\n//\n// Exercise 12.27:\n// The TextQuery and QueryResult classes use only capabilities that we have\n// already covered. Without looking ahead, write your own versions of these\n// classes.\n//\n\n#include \"wy_textquery.h\"\n#include \"wy_queryresult.h\"\n#include \"DebugDelete.h\"\n#include <sstream>\n#include <algorithm>\n\n/**\n *  Constructor\n *  read each line into the dynamicly allocated vector.\n */\nwy_textQuery::wy_textQuery(std::ifstream &fin) :\n    // @oldcode\n    // custom deleter may not use with std::make_shared, as it has an internal\n    // deleter which may not be replaced. As a result, keyword new is the only\n    // option to use with DebugDelete.\n    /*\n    sp_fileData(std::make_shared<std::vector<std::string>>() ),\n    sp_queryMap(std::make_shared<std::map<std::string, std::set<int>>>() )\n    */\n    sp_fileData(new std::vector<std::string>(), DebugDelete() ),\n    sp_queryMap(new std::map<std::string, std::set<int>>(), DebugDelete())\n{\n    std::string line;\n    while(std::getline(fin, line))\n        sp_fileData->push_back(line);\n\n}\n\n/**\n * @brief return a wy_queryResult object for the search result.\n * @param qWord\n */\nwy_queryResult\nwy_textQuery::query(const std::string &qWord) const\n{\n    // storing the amount of occurrence\n    std::size_t counter = 0;\n\n    // loop through each line\n    for(std::size_t i=0; i != sp_fileData->size(); ++i)\n    {\n        // break into each word\n        std::stringstream lineStream((*sp_fileData)[i]);\n        std::string word;\n        while(lineStream >> word)\n        {\n            if(!word.compare(qWord))\n            {\n                ++counter;\n\n                // add the index of the line into the result map\n                (*sp_queryMap)[qWord].insert(i);\n            }\n        }\n    }\n\n    // creare a object holding the result .\n    wy_queryResult qResult(counter, qWord, sp_fileData, sp_queryMap);\n\n    return qResult;\n}\n"
  },
  {
    "path": "ch16/ex16.21.22/wy_textquery.h",
    "content": "/***************************************************************************\n *  @file       wy_textquery.h\n *  @author     Alan.W\n *  @date       27  DEC 2013\n *  @remark\n ***************************************************************************/\n\n//\n// Exercise 12.27:\n// The TextQuery and QueryResult classes use only capabilities that we have\n// already covered. Without looking ahead, write your own versions of these\n// classes.\n//\n\n#ifndef WY_TEXTQUERY_H\n#define WY_TEXTQUERY_H\n\n#include <iostream>\n#include <fstream>\n#include <vector>\n#include <string>\n#include <map>\n#include <set>\n#include <memory>\n\nclass wy_queryResult;\n\nclass wy_textQuery\n{\npublic:\n    typedef std::shared_ptr<std::vector<std::string>> sp_file_Tp;\n    typedef std::shared_ptr<std::map<std::string, std::set<int>>> sp_Qmap_Tp;\n\n    // constructors\n    wy_textQuery() = default;\n    wy_textQuery(std::ifstream &fin);\n\n    // query operation\n    wy_queryResult\n    query(const std::string &qWord) const;\n\nprivate:\n    // smart pointer to a vector to be storing a file.\n    sp_file_Tp sp_fileData = nullptr;\n\n    // smart pointer to a map to be storing results of querries.\n    sp_Qmap_Tp sp_queryMap = nullptr;\n};\n\n#endif // WY_TEXTQUERY_H\n"
  },
  {
    "path": "ch16/ex16.24/Blob.h",
    "content": "/***************************************************************************\n *  @file       Blob.h\n *  @author     Alan.W\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note       03  Feb 2014    Add a constructor that takes two iterators to Blob .\n ***************************************************************************/\n\n#ifndef BLOB_H\n#define BLOB_H\n#include <memory>\n#include <vector>\n\ntemplate<typename T> class Blob\n{\npublic:\n    typedef T value_type;\n    typedef typename std::vector<T>::size_type size_type;\n\n    // constructors\n    Blob();\n    Blob(std::initializer_list<T> il);\n\n    // constructor taking two iterators\n    template<typename It>\n    Blob(It b, It e);\n\n    // number of elements in the Blob\n    size_type size() const { return data->size(); }\n    bool      empty() const{ return data->empty(); }\n\n    void push_back(const T& t) { data->push_back(t); }\n    void push_back(T&& t)      { data->push_back(std::move(t)); }\n    void pop_back();\n\n    // element access\n    T& back();\n    T& operator[](size_type i);\n\n    const T& back() const;\n    const T& operator [](size_type i) const;\n\nprivate:\n    std::shared_ptr<std::vector<T>> data;\n    // throw msg if data[i] isn't valid\n    void check(size_type i, const std::string &msg) const;\n};\n\n//  default constructor\ntemplate<typename T>\nBlob<T>::Blob() : data(std::make_shared<std::vector<T>>())\n{ }\n\n// constructor taking initializer_list\ntemplate<typename T>\nBlob<T>::Blob(std::initializer_list<T> il):\n    data(std::make_shared<std::vector<T>>(il)){ }\n\n// constructor taking two iterators\ntemplate<typename T>    //for class\ntemplate<typename It>   //for this member\nBlob<T>::Blob(It b, It e) :\n    data(std::make_shared<std::vector<T>>(b, e))\n{ }\n\ntemplate<typename T>\nvoid Blob<T>::check(size_type i, const std::string &msg) const\n{\n    if(i >= data->size())\n        throw std::out_of_range(msg);\n}\n\ntemplate<typename T>\nT& Blob<T>::back()\n{\n    check(0, \"back on empty Blob\");\n    return data->back();\n}\n\ntemplate<typename T>\nconst T& Blob<T>::back() const\n{\n    check(0, \"back on empty Blob\");\n    return data->back();\n}\n\n\ntemplate<typename T>\nT& Blob<T>::operator [](size_type i)\n{\n    // if i is too big, check function will throw, preventing access to a nonexistent element\n    check(i, \"subscript out of range\");\n    return (*data)[i];\n}\n\n\ntemplate<typename T>\nconst T& Blob<T>::operator [](size_type i) const\n{\n    // if i is too big, check function will throw, preventing access to a nonexistent element\n    check(i, \"subscript out of range\");\n    return (*data)[i];\n}\n\ntemplate<typename T>\nvoid Blob<T>::pop_back()\n{\n    check(0, \"pop_back on empty Blob\");\n    data->pop_back();\n}\n\n#endif // BLOB_H\n"
  },
  {
    "path": "ch16/ex16.24/blobptr.h",
    "content": "#ifndef BLOBPTR_H\n#define BLOBPTR_H\n\n#include \"Blob.h\"\n#include <memory>\n#include <vector>\n\ntemplate <typename> class BlobPtr;\n\ntemplate <typename T>\nbool operator ==(const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\ntemplate <typename T>\nbool operator < (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\n\ntemplate<typename T> class BlobPtr\n{\n    friend bool operator ==<T>\n    (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\n    friend bool operator < <T>\n    (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);\n\npublic:\n    BlobPtr() : curr(0) { }\n    BlobPtr(Blob<T>& a, std::size_t sz = 0) :\n        wptr(a.data), curr(sz) { }\n\n    T& operator*() const\n    {\n        auto p = check(curr, \"dereference past end\");\n        return (*p)[curr];\n    }\n\n    // prefix\n    BlobPtr& operator++();\n    BlobPtr& operator--();\n\n    // postfix\n    BlobPtr operator ++(int);\n    BlobPtr operator --(int);\n\nprivate:\n    // returns  a shared_ptr to the vector if the check succeeds\n    std::shared_ptr<std::vector<T>>\n         check(std::size_t, const std::string&) const;\n\n    std::weak_ptr<std::vector<T>> wptr;\n    std::size_t curr;\n\n};\n\n// prefix ++\ntemplate<typename T>\nBlobPtr<T>& BlobPtr<T>::operator ++()\n{\n    // if curr already points past the end of the container, can't increment it\n    check(curr, \"increment past end of StrBlob\");\n    ++curr;\n    return *this;\n}\n\n// prefix --\ntemplate<typename T>\nBlobPtr<T>& BlobPtr<T>::operator --()\n{\n    -- curr;\n    check(curr, \"decrement past begin of BlobPtr\");\n\n    return *this;\n}\n\n\n// postfix ++\ntemplate<typename T>\nBlobPtr<T> BlobPtr<T>::operator ++(int)\n{\n    BlobPtr ret = *this;\n    ++*this;\n\n    return ret;\n}\n\n// postfix --\ntemplate<typename T>\nBlobPtr<T> BlobPtr<T>::operator --(int)\n{\n    BlobPtr ret = *this;\n    --*this;\n\n    return ret;\n}\n\n#endif // BLOBPTR_H\n"
  },
  {
    "path": "ch16/ex16.24/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       03  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.24:\n// Add a constructor that takes two iterators to your Blob template.\n//\n\n#include <iostream>\n#include <vector>\n#include <list>\n\n\n#include <memory>\n#include <Blob.h>\n\n\nint main()\n{\n    std::vector<int> v = { 1, 2, 3, 4, 5 };\n    Blob<int> b(v.begin(), v.end());\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.25.26/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       03  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.25:\n// Explain the meaning of these declarations:\n//\n\n/**\n *  @brief  instantiation declaration. The definition of it is somewhere else\n */\n//extern template class vector<string>;\n\n/**\n *  @brief  instantiation definition. The compiler will generate codes for it.\n */\n//template class vector<Sales_data>;\n\n// Exercise 16.26:\n// Assuming NoDefault is a class that does not have a default constructor,\n// can we explicitly instantiate vector<NoDefault>? If not, why not?\n//  http://stackoverflow.com/questions/21525169/while-explicitly-instantiating-vectorsometype-what-is-the-sometype-default-co\n//\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.28/delete.hpp",
    "content": "/***************************************************************************\n*  @file       delete.hpp\n*  @author     Yue Wang\n*  @date       04  Feb 2014\n*                  Jul 2015\n*                  Oct 2015\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n\n#pragma once\n\nnamespace cp5\n{\n    struct Delete\n    {\n        template<typename T>\n        auto operator() (T* p) const\n        {\n            delete p;\n        }\n    };\n}"
  },
  {
    "path": "ch16/ex16.28/main.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Yue Wang\n*  @date       04  Feb 2014\n*                  Jul 2015\n*                  Oct 2015\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 16.28 Write your own versions of shared_ptr and unique_ptr\n//\n\n#include <iostream>\n#include <string>\n#include \"shared_pointer.hpp\"\n\nint main()\n{\n    auto foo = cp5::SharedPointer<int>{ new int(42) };\n    auto bar(foo) ;\n    std::cout << *foo << std::endl;\n    std::cout << foo.use_count() << std::endl;\n\n    auto string_ptr = cp5::SharedPointer<std::string>{ new std::string{ \"Yue\" } };\n    std::cout << *string_ptr << std::endl;\n    std::cout << string_ptr->size() << std::endl;\n\n    return 0;\n}"
  },
  {
    "path": "ch16/ex16.28/shared_pointer.hpp",
    "content": "/***************************************************************************\n*  @file       shared_pointer.hpp\n*  @author     Yue Wang\n*  @date       04  Feb 2014\n*                  Jul 2015\n*                  Oct 2015 \n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n\n#pragma once\n#include <functional>\n#include \"delete.hpp\"\n\nnamespace cp5\n{\n    template<typename T>\n    class SharedPointer;\n\n    template<typename T>\n    auto swap(SharedPointer<T>& lhs, SharedPointer<T>& rhs)\n    {\n        using std::swap;\n        swap(lhs.ptr, rhs.ptr);\n        swap(lhs.ref_count, rhs.ref_count);\n        swap(lhs.deleter, rhs.deleter);\n    }\n\n    template<typename T>\n    class SharedPointer\n    {\n    public:\n        //\n        //  Default Ctor\n        //\n        SharedPointer()\n            : ptr{ nullptr }, ref_count{ new std::size_t(1) }, deleter{ cp5::Delete{} }\n        { }\n        //\n        //  Ctor that takes raw pointer\n        //\n        explicit SharedPointer(T* raw_ptr)\n            : ptr{ raw_ptr }, ref_count{ new std::size_t(1) }, deleter{ cp5::Delete{} }\n        { }\n        //\n        //  Copy Ctor\n        //\n        SharedPointer(SharedPointer const& other)\n            : ptr{ other.ptr }, ref_count{ other.ref_count }, deleter{ other.deleter }\n        {\n            ++*ref_count;\n        }\n        //\n        //  Move Ctor\n        //\n        SharedPointer(SharedPointer && other) noexcept\n            : ptr{ other.ptr }, ref_count{ other.ref_count }, deleter{ std::move(other.deleter) }\n        {\n            other.ptr = nullptr;\n            other.ref_count = nullptr;\n        }\n        //\n        //  Copy assignment\n        //\n        SharedPointer& operator=(SharedPointer const& rhs)\n        {\n            //increment first to ensure safty for self-assignment\n            ++*rhs.ref_count;\n            decrement_and_destroy();\n            ptr = rhs.ptr, ref_count = rhs.ref_count, deleter = rhs.deleter;\n            return *this;\n        }\n        //\n        //  Move assignment\n        //\n        SharedPointer& operator=(SharedPointer && rhs) noexcept\n        {\n            cp5::swap(*this, rhs);\n            rhs.decrement_and_destroy();\n            return *this;\n        }\n        //\n        //  Conversion operator\n        //\n        operator bool() const\n        {\n            return ptr ? true : false;\n        }\n        //\n        //  Dereference\n        //\n        T& operator* () const\n        {\n            return *ptr;\n        }\n        //\n        //  Arrow\n        //\n        T* operator->() const\n        {\n            return &*ptr;\n        }\n        //\n        //  Use count\n        //\n        auto use_count() const\n        {\n            return *ref_count;\n        }\n        //\n        //  Get underlying pointer\n        //\n        auto get() const\n        {\n            return ptr;\n        }\n        //\n        //  Check if the unique user\n        //\n        auto unique() const\n        {\n            return 1 == *refCount;\n        }\n        //\n        //  Swap\n        //\n        auto swap(SharedPointer& rhs)\n        {\n            ::swap(*this, rhs);\n        }\n        //\n        // Free the object pointed to, if unique\n        //\n        auto reset()\n        {\n            decrement_and_destroy();\n        }\n        //\n        // Reset with the new raw pointer\n        //\n        auto reset(T* pointer)\n        {\n            if (ptr != pointer)\n            {\n                decrement_and_destroy();\n                ptr = pointer;\n                ref_count = new std::size_t(1);\n            }\n        }\n        //\n        //  Reset with raw pointer and deleter\n        //\n        auto reset(T *pointer, const std::function<void(T*)>& d)\n        {\n            reset(pointer);\n            deleter = d;\n        }\n        //\n        //  Dtor\n        //\n        ~SharedPointer()\n        {\n            decrement_and_destroy();\n        }\n    private:\n        T* ptr;\n        std::size_t* ref_count;\n        std::function<void(T*)> deleter;\n\n        auto decrement_and_destroy()\n        {\n            if (ptr && 0 == --*ref_count)\n                delete ref_count, \n                deleter(ptr);\n            else if (!ptr)\n                delete ref_count;\n            ref_count = nullptr;\n            ptr = nullptr;\n        }\n    };\n}//namespace\n"
  },
  {
    "path": "ch16/ex16.28/unique_pointer.h",
    "content": "#ifndef UNIQUE_POINTER_H\n#define UNIQUE_POINTER_H\n\n#include <DebugDelete.h>\n\n// forward declarations for friendship\n\ntemplate<typename, typename> class unique_pointer;\ntemplate<typename T, typename D> void\n                swap(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs);\n\n/**\n *  @brief  std::unique_ptr like class template.\n */\ntemplate <typename T, typename D = DebugDelete>\nclass unique_pointer\n{\n    friend void swap<T, D>(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs);\n\npublic:\n    // preventing copy and assignment\n    unique_pointer(const unique_pointer&) = delete;\n    unique_pointer& operator = (const unique_pointer&) = delete;\n\n    // default constructor and one taking T*\n    unique_pointer() = default;\n    explicit unique_pointer(T* up): ptr(up) { }\n\n    // move constructor\n    unique_pointer(unique_pointer&& up) noexcept\n        : ptr(up.ptr)   { up.ptr = nullptr; }\n\n    // move assignment\n    unique_pointer& operator =(unique_pointer&& rhs) noexcept;\n\n    // std::nullptr_t assignment\n    unique_pointer& operator =(std::nullptr_t n) noexcept;\n\n\n\n    // operator overloaded :  *  ->  bool\n    T& operator  *() const   { return *ptr; }\n    T* operator ->() const   { return & this->operator *(); }\n     operator bool() const   { return ptr ? true : false;   }\n\n    // return the underlying pointer\n    T* get() const noexcept { return ptr; }\n\n    // swap member using swap friend\n    void swap(unique_pointer<T, D> &rhs)  { ::swap(*this, rhs); }\n\n    // free and make it point to nullptr or to p's pointee.\n    void reset()     noexcept { deleter(ptr); ptr = nullptr; }\n    void reset(T* p) noexcept { deleter(ptr); ptr = p;       }\n\n    // return ptr and make ptr point to nullptr.\n    T* release();\n\n\n    ~unique_pointer()\n    {\n        deleter(ptr);\n    }\nprivate:\n    T* ptr = nullptr;\n    D  deleter = D();\n};\n\n\n// swap\ntemplate<typename T, typename D>\ninline void\nswap(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs)\n{\n    using std::swap;\n    swap(lhs.ptr, rhs.ptr);\n    swap(lhs.deleter, rhs.deleter);\n}\n\n// move assignment\ntemplate<typename T, typename D>\ninline unique_pointer<T, D>&\nunique_pointer<T, D>::operator =(unique_pointer&& rhs) noexcept\n{\n    // prevent self-assignment\n    if(this->ptr != rhs.ptr)\n    {\n        deleter(ptr);\n        ptr = nullptr;\n        ::swap(*this, rhs);\n    }\n    return *this;\n}\n\n\n// std::nullptr_t assignment\ntemplate<typename T, typename D>\ninline unique_pointer<T, D>&\nunique_pointer<T, D>::operator =(std::nullptr_t n) noexcept\n{\n    if(n == nullptr)\n    {\n        deleter(ptr);   ptr = nullptr;\n    }\n    return *this;\n}\n\n // relinquish contrul by returnning ptr and making ptr point to nullptr.\ntemplate<typename T, typename D>\ninline T*\nunique_pointer<T, D>::release()\n{\n    T* ret = ptr;\n    ptr = nullptr;\n    return ret;\n}\n#endif // UNIQUE_POINTER_H\n"
  },
  {
    "path": "ch16/ex16.29/Blob.h",
    "content": "/***************************************************************************\n *  @file       Blob.h\n *  @author     Alan.W\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note       03  Feb 2014    Add a constructor that takes two iterators to Blob .\n *              06  Feb 2014    revise to use custome shared_ptr\n ***************************************************************************/\n\n#ifndef BLOB_H\n#define BLOB_H\n#include <memory>\n#include <vector>\n#include \"shared_pointer.h\"\n\n/**\n *  Blob\n *  manage a vector through a shared_pointer.\n */\ntemplate<typename T> class Blob\n{\npublic:\n    typedef T value_type;\n    typedef typename std::vector<T>::size_type size_type;\n\n    // constructors\n    Blob();\n    Blob(std::initializer_list<T> il);\n\n    // constructor taking two iterators\n    template<typename It>\n    Blob(It b, It e);\n\n    // number of elements in the Blob\n    size_type size() const { return data->size(); }\n    bool      empty() const{ return data->empty(); }\n\n    void push_back(const T& t) { data->push_back(t); }\n    void push_back(T&& t)      { data->push_back(std::move(t)); }\n    void pop_back();\n\n    // element access\n    T& back();\n    T& operator[](size_type i);\n\n    const T& back() const;\n    const T& operator [](size_type i) const;\n\nprivate:\n    /**\n     * @oldcode updated Feb 06, 2014 @Alan\n     */\n    //std::shared_ptr<std::vector<T>> data;\n\n    shared_pointer<std::vector<T>> data;\n\n    // throw msg if data[i] isn't valid\n    void check(size_type i, const std::string &msg) const;\n};\n\n//  default constructor\ntemplate<typename T>\nBlob<T>::Blob() : data(std::make_shared<std::vector<T>>())\n{ }\n\n// constructor taking initializer_list\ntemplate<typename T>\nBlob<T>::Blob(std::initializer_list<T> il):\n    data(std::make_shared<std::vector<T>>(il)){ }\n\n// constructor taking two iterators\ntemplate<typename T>    //for class\ntemplate<typename It>   //for this member\nBlob<T>::Blob(It b, It e) :\n    data(std::make_shared<std::vector<T>>(b, e))\n{ }\n\ntemplate<typename T>\nvoid Blob<T>::check(size_type i, const std::string &msg) const\n{\n    if(i >= data->size())\n        throw std::out_of_range(msg);\n}\n\ntemplate<typename T>\nT& Blob<T>::back()\n{\n    check(0, \"back on empty Blob\");\n    return data->back();\n}\n\ntemplate<typename T>\nconst T& Blob<T>::back() const\n{\n    check(0, \"back on empty Blob\");\n    return data->back();\n}\n\n\ntemplate<typename T>\nT& Blob<T>::operator [](size_type i)\n{\n    // if i is too big, check function will throw, preventing access to a nonexistent element\n    check(i, \"subscript out of range\");\n    return (*data)[i];\n}\n\n\ntemplate<typename T>\nconst T& Blob<T>::operator [](size_type i) const\n{\n    // if i is too big, check function will throw, preventing access to a nonexistent element\n    check(i, \"subscript out of range\");\n    return (*data)[i];\n}\n\ntemplate<typename T>\nvoid Blob<T>::pop_back()\n{\n    check(0, \"pop_back on empty Blob\");\n    data->pop_back();\n}\n\n#endif // BLOB_H\n"
  },
  {
    "path": "ch16/ex16.29/DebugDelete.h",
    "content": "/***************************************************************************\n *  @file       DebugDelete.h\n *  @author     Alan.W\n *  @date       04  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n\n#ifndef DEBUGDELETE_H\n#define DEBUGDELETE_H\n\n#include <iostream>\n\n/**\n * @brief The DebugDelete class is a deleter functor using delete\n */\nclass DebugDelete\n{\npublic:\n    DebugDelete(std::ostream& s = std::cerr) : os(s) { }\n    template<typename T>\n    void operator() (T* p) const\n    {\n        os << \"deleting ptr\" << std::endl;\n        delete p;\n    }\n\nprivate:\n    std::ostream& os;\n};\n#endif // DEBUGDELETE_H\n"
  },
  {
    "path": "ch16/ex16.29/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       04  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.29:\n// Revise your Blob class to use your version of shared_ptr rather than the\n// library version.\n//\n\n\n#include <iostream>\n#include <vector>\n#include <memory>\n#include <functional>\n#include \"DebugDelete.h\"\n#include \"shared_pointer.h\"\n#include \"unique_pointer.h\"\n#include \"Blob.h\"\n\nint main()\n{\n    Blob<std::string> b;\n    b.push_back(\"sss\");\n\n\n    b[0] = \"zzzz\";\n    std::cout << b[0] << \"\\n\";\n}\n"
  },
  {
    "path": "ch16/ex16.29/shared_pointer.h",
    "content": "/***************************************************************************\n *  @file       shared_pointer.h\n *  @author     Alan.W\n *  @date       04  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note       06  Feb 2014    ctor taking std::shared_ptr&& added\n ***************************************************************************/\n#ifndef SHARED_POINTER_H\n#define SHARED_POINTER_H\n\n#include \"DebugDelete.h\"\n#include <functional>\n#include <memory>\n\n// forward declarations needed for friendship\n\ntemplate<typename> class shared_pointer;\ntemplate<typename T> void swap(shared_pointer<T>& lhs, shared_pointer<T>& rhs);\n\n\n/**\n *  @brief shared_ptr like template class\n *  @note   don't mix this one with std::shared_ptr.\n *          DebugDelete is the default deleter which can be replaced at run time\n */\ntemplate <typename T>\nclass shared_pointer\n{\n    friend void ::swap<T>(shared_pointer<T>& lhs, shared_pointer<T>& rhs);\n    //               ^^^ -- don't forget this.\n\npublic:\n\n    // default constructor\n    shared_pointer() = default;\n\n    // constructor taking raw pointer.\n    // set the refCount as 1\n    explicit shared_pointer(T* up, std::function<void(T*)> d = DebugDelete()) :\n        ptr(up), refCount(new std::size_t(1)), deleter(d) { }\n\n    // ctor taking std::shared_ptr&& i.e. rvalue reference\n    explicit shared_pointer(std::shared_ptr<T>&& sp,\n                            std::function<void(T*)> d = DebugDelete());\n\n    // copy constructor.\n    // increment useCount for each Copy\n    shared_pointer(const shared_pointer& sp):\n        ptr(sp.ptr), refCount(sp.refCount), deleter(sp.deleter)\n    { ++*refCount; }\n\n    // move constructor\n    shared_pointer(shared_pointer&& sp) noexcept;\n\n    // copy assignment\n    shared_pointer& operator =(const shared_pointer& rhs);\n\n    // move assignment\n    shared_pointer& operator =(shared_pointer&& rhs) noexcept;\n\n\n    // conversion operator\n    operator bool() const { return ptr ? true : false; }\n\n    // dereference *     arrow ->\n    T& operator* () const { return *ptr; }\n    T* operator->() const { return & this->operator *(); }\n\n    // return useCount\n    std::size_t use_count() const { return *refCount; }\n\n    // get the underlying pointer\n    T* get() const noexcept { return ptr; }\n\n    // check if the unique user\n    bool unique() const noexcept { return *refCount == 1; }\n\n    // swap member\n    void swap( shared_pointer& rhs) { ::swap(*this, rhs); }\n\n    // if unique user, free the object pointed to\n    void reset() noexcept { decrement_n_destroy(); }\n\n    // make prt point where p pointing and create a new coount for it\n    void reset(T* p);\n\n    // reset to point where p is pointing and change deleter to d.\n    void reset(T *p, const std::function<void(T*)>& d)\n    {   reset(p);   deleter = d;   }\n\n\n    ~shared_pointer()\n    {\n        decrement_n_destroy();\n    }\nprivate:\n\n    T* ptr = nullptr;\n    std::size_t* refCount = new std::size_t(0);\n\n    // any functor lambda or function pointer that matched this\n    // signature can replace the default one at run time.\n    std::function<void(T*)> deleter{ DebugDelete() };\n    //                            ^~~~~~~~~~~~~~^\n    //                         here: = doesn't work, another way is initializing it in constructor.\n\n    // utilities\n    void decrement_n_destroy();\n};\n\n\n\n/**\n *  @brief swap and big 5\n */\ntemplate <typename T>\ninline void\nswap(shared_pointer<T>& lhs, shared_pointer<T>& rhs)\n{\n    using std::swap;\n    swap(lhs.ptr, rhs.ptr);\n    swap(lhs.refCount, rhs.refCount);\n    swap(lhs.deleter, rhs.deleter);\n}\n\n\n/**\n *  @brief  ctor taking std::shared_ptr&& i.e. rvalue reference\n *  an interface between shared_pointer and std::shared_ptr.\n *  only rvalue AND unique ownership can use this ctor.\n */\ntemplate <typename T>\ninline\nshared_pointer<T>::shared_pointer(std::shared_ptr<T>&& sp,\n                                  std::function<void(T*)> d)\n{\n    if(sp.unique())\n        *this = shared_pointer(new T(*sp), d);\n    else\n        throw std::runtime_error\n            (\"only unique and rvalue reference can transfer ownership--@Alan\\n\");\n}\n\n\n// move constructor\ntemplate<typename T>\ninline\nshared_pointer<T>::shared_pointer(shared_pointer&& sp) noexcept:\n    ptr(sp.ptr), refCount(sp.refCount), deleter(std::move(sp.deleter))\n{\n    sp.ptr = nullptr;\n    sp.refCount = nullptr;\n}\n\n\n// copy assignment\ntemplate<typename T>\ninline shared_pointer<T>&\nshared_pointer<T>::operator =(const shared_pointer& rhs)\n{\n    // increment rhs.refCount first to ensure safty when self-assignment\n    ++*rhs.refCount;\n\n    // for lhs:\n    decrement_n_destroy();\n\n    // copy datastructure from rhs to this.\n    ptr = rhs.ptr;\n    refCount = rhs.refCount;\n    deleter  = rhs.deleter;\n\n    return *this;\n}\n\n\n// move assignment\ntemplate<typename T>\ninline shared_pointer<T>&\nshared_pointer<T>::operator =(shared_pointer&& rhs) noexcept\n{\n    // for lhs\n    decrement_n_destroy();\n\n    // swap two sides\n    ::swap(*this, rhs);\n\n    std::cout << \"shared_pointer::move=\\n\";\n\n    return *this;\n}\n\n\n// make prt point where p pointing and create a new coount for it\ntemplate<typename T>\ninline void\nshared_pointer<T>::reset(T* p)\n{\n    if(ptr != p)\n    {\n        decrement_n_destroy();\n        ptr = p;\n        refCount = new std::size_t(1);\n    }\n}\n\n\n/**\n *@brief operators: <<\n **/\n\ntemplate <typename T>\ninline std::ostream&\noperator <<(std::ostream& os, shared_pointer<T> p)\n{\n    os << p.get();\n    return os;\n}\n\n\n// utilities for decrement and delete using deleter.\ntemplate <typename T>\ninline void\nshared_pointer<T>::decrement_n_destroy()\n{\n    if(ptr)\n    {\n        if (--*refCount == 0)\n        {\n            delete refCount;\n            deleter(ptr);\n        }\n        refCount = nullptr;\n        ptr = nullptr;\n    }\n}\n\n#endif // SHARED_POINTER_H\n"
  },
  {
    "path": "ch16/ex16.29/unique_pointer.h",
    "content": "#ifndef UNIQUE_POINTER_H\n#define UNIQUE_POINTER_H\n\n#include \"DebugDelete.h\"\n\n// forward declarations for friendship\n\ntemplate<typename, typename> class unique_pointer;\ntemplate<typename T, typename D> void\n                swap(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs);\n\n/**\n *  @brief  std::unique_ptr like class template.\n */\ntemplate <typename T, typename D = DebugDelete>\nclass unique_pointer\n{\n    friend void swap<T, D>(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs);\n\npublic:\n    // preventing copy and assignment\n    unique_pointer(const unique_pointer&) = delete;\n    unique_pointer& operator = (const unique_pointer&) = delete;\n\n    // default constructor and one taking T*\n    unique_pointer() = default;\n    explicit unique_pointer(T* up): ptr(up) { }\n\n    // move constructor\n    unique_pointer(unique_pointer&& up) noexcept\n        : ptr(up.ptr)   { up.ptr = nullptr; }\n\n    // move assignment\n    unique_pointer& operator =(unique_pointer&& rhs) noexcept;\n\n    // std::nullptr_t assignment\n    unique_pointer& operator =(std::nullptr_t n) noexcept;\n\n\n\n    // operator overloaded :  *  ->  bool\n    T& operator  *() const   { return *ptr; }\n    T* operator ->() const   { return & this->operator *(); }\n     operator bool() const   { return ptr ? true : false;   }\n\n    // return the underlying pointer\n    T* get() const noexcept { return ptr; }\n\n    // swap member using swap friend\n    void swap(unique_pointer<T, D> &rhs)  { ::swap(*this, rhs); }\n\n    // free and make it point to nullptr or to p's pointee.\n    void reset()     noexcept { deleter(ptr); ptr = nullptr; }\n    void reset(T* p) noexcept { deleter(ptr); ptr = p;       }\n\n    // return ptr and make ptr point to nullptr.\n    T* release();\n\n\n    ~unique_pointer()\n    {\n        deleter(ptr);\n    }\nprivate:\n    T* ptr = nullptr;\n    D  deleter = D();\n};\n\n\n// swap\ntemplate<typename T, typename D>\ninline void\nswap(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs)\n{\n    using std::swap;\n    swap(lhs.ptr, rhs.ptr);\n    swap(lhs.deleter, rhs.deleter);\n}\n\n// move assignment\ntemplate<typename T, typename D>\ninline unique_pointer<T, D>&\nunique_pointer<T, D>::operator =(unique_pointer&& rhs) noexcept\n{\n    // prevent self-assignment\n    if(this->ptr != rhs.ptr)\n    {\n        deleter(ptr);\n        ptr = nullptr;\n        ::swap(*this, rhs);\n    }\n    return *this;\n}\n\n\n// std::nullptr_t assignment\ntemplate<typename T, typename D>\ninline unique_pointer<T, D>&\nunique_pointer<T, D>::operator =(std::nullptr_t n) noexcept\n{\n    if(n == nullptr)\n    {\n        deleter(ptr);   ptr = nullptr;\n    }\n    return *this;\n}\n\n // relinquish contrul by returnning ptr and making ptr point to nullptr.\ntemplate<typename T, typename D>\ninline T*\nunique_pointer<T, D>::release()\n{\n    T* ret = ptr;\n    ptr = nullptr;\n    return ret;\n}\n#endif // UNIQUE_POINTER_H\n"
  },
  {
    "path": "ch16/ex16.32.33.34.35.36/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang, Mugurell\n *  @date       04  Feb 2014\n *              Aug, 2015\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.32:\n// What happens during template argument deduction?\n//  The process of determining the template arguments from the function arguments\n//  is known as template argument deduction. During template argument deduction,\n//  the compiler uses types of the arguments in the call to find the template\n//  arguments that generate a version of the function that best matches the given\n//  call.\n//\n// Exercise 16.33:\n// Name two type conversions allowed on function arguments involved in template\n// argument deduction.\n//  • const conversions: A function parameter that is a reference (or pointer)\n//  to a const can be passed a reference (or pointer) to a nonconst object\n//  (§ 4.11.2, p. 162).\n//\n//  • Array- or function-to-pointer conversions: If the function parameter is\n//  not a reference type, then the normal pointer conversion will be applied\n//  to arguments of array or function type. An array argument will be converted\n//  to a pointer to its first element. Similarly, a function argument will be\n//  converted to a pointer to the function’s type (§ 4.11.2, p. 161).\n//\n// Exercise 16.34:\n// Given only the following code, explain whether each of these calls is legal.\n// If so, what is the type of T? If not, why not?\n//     template <class T> int compare(const T&, const T&);\n//          compare(\"hi\", \"world\");\n//  It didn't complie, as two types are different, the first type being char[3] , second char[6]\n//          compare(\"bye\", \"dad\");\n//   the type should be pointer to char i.e. char*\n//\n// Exercise 16.35:\n// Which, if any, of the following calls are errors? If the call is legal, what\n// is the type of T? If the call is not legal, what is the problem?\n//      template <typename T> T calc(T, int);\n//      template <typename T> T fcn(T, T);\n//         double d;    float f;    char c;\n//         (a) calc(c, 'c');   -- legal, T is a char\n//         (b) calc(d, f);     -- legal, T is a double\n//         (c) fcn(c, 'c');    -- legal, T is a char\n//         (d) fcn(d, f);      -- illegal, arguments d and f are double and float repectively\n//\n// Exercise 16.36:\n// What happens in the following calls:\n//         template <typename T> f1(T, T);\n//         template <typename T1, typename T2) f2(T1, T2);\n//         int i = 0, j = 42, *p1 = &i, *p2 = &j;\n//         const int *cp1 = &i, *cp2 = &j;\n//             (a) f1(p1, p2);     // f1<int*>(int*, int*)\n//             (b) f2(p1, p2);     // f2<int*, int*>(int*, int*)\n//             (c) f1(cp1, cp2);   // f1<int const*>(int const*, int const*)\n//             (d) f2(cp1, cp2);   // f2<int const*, int const*>(int const*, int const*)\n//             (e) f1(p1, cp1);    // deduced conflicting types for parameter 'T'\n//             (f) f2(p1, cp1);    // f2<int*, int const*>(int*, int const*)\n//\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.37.38.39/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       07  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.37:\n// The library max function has two function parameters and returns the\n// larger of its arguments. This function has one template type parameter.\n// Could you call max passing it an int and a double? If so, how? If not,\n// why not?\n//  Yes, just offer an explicit template argument, like:\n//  int a = 1;\n//  double b = 2;\n//  std::max<double>(a, b);\n//\n// Exercise 16.38:\n// When we call make_shared (§ 12.1.1, p. 451), we have to provide an\n// explicit template argument. Explain why that argument is needed and\n// how it is used.\n//\n//  without specified type given, make_shared has no possibility to\n//  to determine how big the size it should allocate, which is the reason.\n//\n//  Depending on the type specified, make_shared allocates proper size of memory\n//  space and returns a proper type of shared_ptr pointing to it.\n//\n// Exercise 16.39:\n// Use an explicit template argument to make it sensible to pass two string\n// literals to the original version of compare from § 16.1.1 (p. 652).\n//\n\n\n#include <iostream>\n\n\ntemplate <typename T>\nint compare(const T &v1, const T &v2)\n{\n    if (v1 < v2) return -1;\n    if (v2 < v1) return 1;\n    return 0;\n}\n\nint main()\n{\n    std::cout << compare<std::string>(\"sss\",\"aaa\") << \"\\n\";\n}\n"
  },
  {
    "path": "ch16/ex16.4/main.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Yue Wang\n*  @date       02  Feb 2014\n*              18  Jun 2015\n*                  Nov 2015\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 16.4:\n// Write a template that acts like the library find algorithm. The function\n// will need two template type parameters, one to represent the function’s\n// iterator parameters and the other for the type of the value. Use your\n// function to find a given value in a vector<int> and in a list<string>.\n//\n\n#include <iostream>\n#include <vector>\n#include <list>\n#include <string>\n\nnamespace ch16\n{\n    template<typename Iterator, typename Value>\n    auto find(Iterator first, Iterator last, Value const& value)\n    {\n        for (; first != last && *first != value; ++first);\n        return first;\n    }\n}\n\nint main()\n{\n    std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    auto is_in_vector = v.cend() != ch16::find(v.cbegin(), v.cend(), 5);\n    std::cout << (is_in_vector ? \"found\\n\" : \"not found\\n\");\n\n    std::list<std::string> l = { \"aa\", \"bb\", \"cc\", \"dd\", \"ee\", \"ff\", \"gg\" };\n    auto is_in_list = l.cend() != ch16::find(l.cbegin(), l.cend(), \"zz\");\n    std::cout << (is_in_list ? \"found\\n\" : \"not found\\n\");\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.40/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       07  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.40:\n// Is the following function legal? If not, why not? If it is legal, what,\n// if any, are the restrictions on the argument type(s) that can be passed,\n// and what is the return type?\n// legal.\n// As shown below, only type that support this + 0 operation can be passed.\n// the return type depends on the what type the operator + returns. In the case\n// below, the return type is Bar.\n//\n\n\n#include <iostream>\n#include <vector>\n#include <string>\n\nclass Bar{ };\n\nBar operator +(Bar lhs, int)\n{\n    return lhs;\n}\n\ntemplate <typename It>\nauto fcn3(It beg, It end) -> decltype(*beg + 0)\n{\n    return *beg;  // return a copy of an element from the range\n}\n\nint main()\n{\n    std::vector<Bar> v;\n    v.push_back(Bar());\n    Bar b = fcn3(v.begin(), v.end());\n    ;\n    ;\n}\n"
  },
  {
    "path": "ch16/ex16.41/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       07  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.41:\n// Write a version of sum with a return type that is guaranteed to be large\n// enough to hold the result of the addition.\n//\n\n\n#include <iostream>\n#include <vector>\n#include <string>\n\ntemplate<typename T>\nauto sum(T lhs, T rhs) -> decltype( lhs + rhs)\n{\n    return lhs + rhs;\n}\n\nint main()\n{\n    auto s= sum(123456789123456789123456789123456789123456789, 123456789123456789123456789123456789123456789) ;\n    ;\n    ;\n}\n"
  },
  {
    "path": "ch16/ex16.42.43.44.45.46/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       07  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.42:\n// Determine the type of T and of val in each of the following calls:\n//     template <typename T> void g(T&& val);\n//     int i = 0; const int ci = i;\n//     (a) g(i);\n//  since i is lvalue, T is deduced as int&, val is int& && collapsing to int&\n//     (b) g(ci);\n//  since ci is lvaue, T is deduced as const int&, val is const int& && collapsing to const int&\n//     (c) g(i * ci);\n//  since i * ci is rvalue, T is deduced as int, val is int&& && colapsing to int&&\n//\n// Exercise 16.43:\n// Using the function defined in the previous exercise, what would the template\n// parameter of g be if we called g(i = ci)?\n//      (i = ci) returns lvalue refering to the object i.\n//      Hence T is deduced as int& val is int& && .\n//      any change on val changes the object i.\n//\n// Exercise 16.44:\n// Using the same three calls as in the first exercise, determine the types for T\n// if g’s function parameter is declared as T (not T&&).\n//                                           ^\n//      g(i);       --  T is deduced as int\n//      g(ci);      --  T is deduced as int, const is ignored.\n//      g(i * ci);  --  T is deduced as int, (i * ci) returns rvalue which is copied to\n//                      T\n// What if g’s function parameter is const T&?\n//                                    ^^^^^^^^\n//      g(i)        --  T is deduced as int  , val : const int&\n//      g(ci)       --  T is deduced as int  , val : const int&\n//      g(i * ci)   --  T is deduced as int  , val : const int&(see example on page 687)\n//\n// Exercise 16.45:\n// Given the following template, explain what happens if we call g on a literal value\n// such as 42. What if we call g on a variable of type int?\n//     template <typename T> void g(T&& val) { vector<T> v; }\n//\n// Discussion on SO:\n//  http://stackoverflow.com/questions/21624016/when-a-lvalue-is-passed-to-t-what-will-happen\n//\n//     relevant section from textbook:\n// When we pass an lvalue (e.g., i) to a function parameter that is an rvalue reference to a\n// template type parameter (e.g, T&&), the compiler deduces the template type parameter as the\n// argument’s lvalue reference type. So, when we call f3(i), the compiler deduces the type of\n// T as int&, not int.\n//         --  P.688\n//\n// In this case, when calling on a literal value, say 42. int&& && will collapse to int&&. At last\n// T is deduced as int. Hence std::vector<T> is instantiated as std::vector<int> which is legal.\n//\n// When calling on a variable int. T will be deduced as int&. int & && will collapse to int&.\n// std::vector<int&> is not legal. The reason why int& can't be element of a vector can be found at:\n//  http://stackoverflow.com/questions/922360/why-cant-i-make-a-vector-of-references\n//\n// Exercise 16.46:\n// Explain this loop from StrVec::reallocate in § 13.5 (p. 530):\n//\n//         for (size_t i = 0; i != size(); ++i)\n//             alloc.construct(dest++, std::move(*elem++));\n//\n// In each iteration, the dereference operator * returns a lvalue which is changed to rvalue by\n// std::move , becasue the member function construct takes rvalue reference rather than lvalue\n// reference.\n//\n\n\n\n\n#include <iostream>\n#include <vector>\n#include <string>\n\ntemplate <typename T>\nvoid g(T&& val)\n{\n    std::vector<T> v;\n}\n\nint main()\n{\n    std::allocator a;\n    a.construct\n}\n"
  },
  {
    "path": "ch16/ex16.47/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       07  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.47:\n// Write your own version of the flip function\n// and test it by calling functions that have lvalue and rvalue reference parameters.\n//\n\n#include <iostream>\n#include <memory>\n\nvoid func_lvalue(std::string& lhs, std::string& rhs)\n{\n    lhs = \"Wang\\n\";\n    rhs = \"Alan\\n\";\n}\n\nvoid func_rvalue(int&& lhs, int&& rhs)\n{\n    // allocate enough space\n    std::allocator<int> alloc;\n    int* data(alloc.allocate(3));\n\n    // move into the spaced newly allocated\n    alloc.construct(data    , lhs);\n    alloc.construct(data +1 , 0);\n    alloc.construct(data +2 , rhs);\n\n    // print\n    for (auto p = data; p != data + 3;  ++p)\n        std::cout << *p << \"\\n\";\n\n    // destroy and deallocation\n    for (auto p = data +3; p != data;    )\n        alloc.destroy(--p);\n    alloc.deallocate(data, 3);\n}\n\ntemplate<typename F, typename T1, typename T2>\nvoid flip(F f, T1&& t1, T2&& t2)\n{\n    f(std::forward<T2>(t2), std::forward<T1>(t1));\n}\n\nint main()\n{\n    // test for lvalue reference\n    /*\n    std::string s1, s2;\n    flip(func_lvalue, s1, s2);\n    std::cout << s1 << s2;\n    */\n\n    // test for rvalue reference\n    flip(func_rvalue, 99, 88);\n\n\n}\n"
  },
  {
    "path": "ch16/ex16.48/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       07  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.48:\n// Write your own versions of the debug_rep functions.\n//\n\n#include <iostream>\n#include <memory>\n#include <sstream>\n\n\n// always declare first:\n\ntemplate <typename T> std::string debug_rep(const T& t);\ntemplate <typename T> std::string debug_rep(T* p);\n\nstd::string debug_rep(const std::string &s);\nstd::string debug_rep(char* p);\nstd::string debug_rep(const char *p);\n\n\n\n\n// print any type we don't otherwise.\ntemplate<typename T> std::string debug_rep(const T& t)\n{\n    std::ostringstream ret;\n    ret << t;\n    return ret.str();\n}\n\n// print pointers as their pointer value, followed by the object to which the pointer points\ntemplate<typename T> std::string debug_rep(T* p)\n{\n    std::ostringstream ret;\n    ret << \"pointer: \" << p;\n\n    if(p)\n        ret << \" \" << debug_rep(*p);\n    else\n        ret << \" null pointer\";\n\n    return ret.str();\n}\n\n// non-template version\nstd::string debug_rep(const std::string &s)\n{\n    return '\"' + s + '\"';\n}\n\n// convert the character pointers to string and call the string version of debug_rep\nstd::string debug_rep(char *p)\n{\n    return debug_rep(std::string(p));\n}\n\nstd::string debug_rep(const char *p)\n{\n    return debug_rep(std::string(p));\n}\n\nint main()\n{\n\n\n\n}\n"
  },
  {
    "path": "ch16/ex16.49.50/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       07  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.49:\n// Explain what happens in each of the following calls:\n//\n// Exercise 16.50:\n// Define the functions from the previous exercise so that they print an\n// identifying message. Run the code from that exercise. If the calls behave\n// differently from what you expected, make sure you understand why.\n//\n\n#include <iostream>\n#include <memory>\n#include <sstream>\n\ntemplate <typename T> void f(T)\n{\n    std::cout << \"f(T)\\n\";\n}\n\ntemplate <typename T> void f(const T*)\n{\n    std::cout << \"f(const T*)\\n\";\n}\ntemplate <typename T> void g(T)\n{\n    std::cout << \"template <typename T> void g(T)\\n\";\n}\ntemplate <typename T> void g(T*)\n{\n    std::cout << \"template <typename T> void g(T*)\\n\";\n}\n\n\n\nint main()\n{\n    int i = 42, *p = &i;\n    const int ci = 0, *p2 = &ci;\n\n    //g(42);    //template <typename T> void g(T ); --is called\n    //g(p);     //template <typename T> void g(T*); --is called\n    //g(ci);      //template <typename T> void g(T)   --is called\n    //g(p2);      //template <typename T> void g(T*)    --is called\n    //f(42);    //f(T)\n    //f(p);     //f(T)\n    //f(ci);    //f(T)\n    f(p2);      //f(const T*)\n\n\n\n}\n"
  },
  {
    "path": "ch16/ex16.5/main.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Yue Wang\n*  @date       02  Feb 2014\n*              13  Oct 2014\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 16.5:\n// Write a template version of the print function from § 6.2.4 (p. 217) that\n// takes a reference to an array and can handle arrays of any size and any\n// element type.\n//\n\n#include <iostream>\n#include <string>\n\ntemplate<typename Arr>\nvoid print(Arr const& arr)\n{\n    for (auto const& elem : arr)\n        std::cout << elem << std::endl;\n}\n\nint main()\n{\n    std::string s[] = { \"ssss\", \"aaa\", \"ssssss\" };\n    char c[] = { 'a', 'b', 'c', 'd' };\n    int  i[] = { 1 };\n    print(i);\n    print(c);\n    print(s);\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.51.52/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       12  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.51:\n// Determine what sizeof...(Args) and sizeof...(rest) return for each call to foo in this section.\n//\n// Exercise 16.52:\n// Write a program to check your answer to the previous question.\n//\n\n#include <iostream>\n\ntemplate<typename T, typename ...Args>\nvoid foo(T t, Args ...args)\n{\n    std::cout << sizeof...(Args) << std::endl;\n    std::cout << sizeof...(args) << std::endl;\n}\n\n\nint main()\n{\n    foo(1, 2);\n    foo(1, 23, 4, 5, 6);\n}\n"
  },
  {
    "path": "ch16/ex16.53.54.55/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       16  Feb 2014\n                Aug, 2015\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.53:\n// Write your own version of the print functions and test them by printing\n// one, two, and five arguments, each of which should have different types.\n//\n// Exercise 16.54:\n// What happens if we call print on a type that doesn’t have an << operator?\n//  It didn't  compile.\n//\n// Exercise 16.55:\n// Explain how the variadic version of print would execute if we declared\n// the nonvariadic version of print after the definition of the variadic\n// version.\n//  error: no matching function for call to 'print(std::ostream&)'\n//\n\n#include <iostream>\n\n// trivial case \ntemplate<typename Printable>\nstd::ostream& print(std::ostream& os, Printable const& printable)\n{\n    return os << printable;\n}\n// recursion\ntemplate<typename Printable, typename... Args>\nstd::ostream& print(std::ostream& os, Printable const& printable, Args const&... rest)\n{\n    return print(os << printable << \", \", rest...);\n}\n\nint main()\n{\n    print(std::cout, 1) << std::endl;\n    print(std::cout, 1, 2) << std::endl;\n    print(std::cout, 1, 2, 3, 4, \"sss\", 42.4242) << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.56.57/main.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Yue Wang\n*  @date       16  Feb 2014\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 16.56:\n// Write and test a variadic version of errorMsg.\n//\n// Exercise 16.57:\n// Compare your variadic version of errorMsg to the error_msg function in\n// § 6.2.6 (p. 220). What are the advantages and disadvantages of each\n// approach?\n//  The error_msg takes initializer_list as the argument. So only the elements\n//  stored in it must be the same or at least convertible. In contrast, the variadic\n//  version provides better flexibility.\n//\n\n#include <iostream>\n#include <memory>\n#include <sstream>\n\n// always declare first:\ntemplate <typename T> \nstd::string debug_rep(const T& t);\ntemplate <typename T> \nstd::string debug_rep(T* p);\n\nstd::string debug_rep(const std::string &s);\nstd::string debug_rep(char* p);\nstd::string debug_rep(const char *p);\n\n// print any type we don't otherwise.\ntemplate<typename T> \nstd::string debug_rep(const T& t)\n{\n    std::ostringstream ret;\n    ret << t;\n    return ret.str();\n}\n\n// print pointers as their pointer value, followed by the object to which the pointer points\ntemplate<typename T> \nstd::string debug_rep(T* p)\n{\n    std::ostringstream ret;\n    ret << \"pointer: \" << p;\n\n    if (p)\n        ret << \" \" << debug_rep(*p);\n    else\n        ret << \" null pointer\";\n\n    return ret.str();\n}\n\n// non-template version\nstd::string debug_rep(const std::string &s)\n{\n    return '\"' + s + '\"';\n}\n\n// convert the character pointers to string and call the string version of debug_rep\nstd::string debug_rep(char *p)\n{\n    return debug_rep(std::string(p));\n}\n\nstd::string debug_rep(const char *p)\n{\n    return debug_rep(std::string(p));\n}\n\n// function to end the recursion and print the last element\n// this function must be declared before the variadic version of\n// print is defined\ntemplate<typename T>\nstd::ostream& print(std::ostream& os, const T& t)\n{\n    return os << t;\n    //           ^\n    // note: no seperator after the last element in the pack\n}\n\n// this version of print will be called for all but the last element in the pack\ntemplate<typename T, typename... Args>\nstd::ostream& print(std::ostream &os, const T &t, const Args&... rest)\n{\n    // print the first argument\n    os << t << \",\";\n\n    // recursive call; print the other arguments\n    return print(os, rest...);\n}\n\n// call debug_rep on each argument in the call to print\ntemplate<typename... Args>\nstd::ostream& errorMsg(std::ostream& os, const Args... rest)\n{\n    return print(os, debug_rep(rest)...);\n}\n\nint main()\n{\n    errorMsg(std::cout, 1, 2, 3, 4, 9.0f, \"sss\", \"alan\");\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.58.59/strvec.cpp",
    "content": "/***************************************************************************\n *  @file       strvec.cpp\n *  @author     Alan.W\n *  @date       05  JAN 2014\n *  @remark     16  Feb 2014 : emplace_back added\n ***************************************************************************/\n\n#include \"strvec.h\"\n#include <memory>\n\n\n// copy constructor\nStrVec::StrVec(const StrVec &s)\n{\n    /**\n     * @brief newData is a pair of pointers pointing to newly allocated and copied\n     *                  range : [b, e)\n     */\n    std::pair<std::string*, std::string*>\n            newData = alloc_n_copy(s.begin(), s.end());\n\n    element = newData.first;\n    first_free = cap = newData.second;\n}\n\n/**\n * @brief   constructor taking initializer_list<string>\n *          for ex 13.40\n * @param l\n */\nStrVec::StrVec(std::initializer_list<std::string> l)\n{\n    // allocate memory as large as l.size()\n    std::string * const\n            newData = alloc.allocate(l.size());\n\n    // copy elements from l to the address allocated\n    auto p = newData;\n    for(const auto &s : l)\n        alloc.construct(p++, s);\n\n    // build the data structure\n    element = newData;\n    first_free = cap = element + l.size();\n}\n\n\n// operator =\nStrVec&\nStrVec::operator =(const StrVec& rhs)\n{\n    // allocate and copy first to protect against self-assignment\n    std::pair<std::string*, std::string*>\n            newData = alloc_n_copy(rhs.begin(), rhs.end());\n\n    // destroy and deallocate\n    free();\n\n    element = newData.first;\n    first_free = cap = newData.second;\n\n    return *this;\n}\n\n// destructor\nStrVec::~StrVec()\n{\n    free();\n}\n\n/**\n * @brief   allocate new room if nessary and push back the new string\n * @param s new string\n */\nvoid StrVec::push_back(const std::string& s)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, s);\n}\n\n/**\n * @brief   preallocate enough memory for specified number of elements\n * @param n number of elements required\n * @note    this function is implemented refering to StrVec::reallocate().\n */\nvoid StrVec::reserve(std::size_t n)\n{\n    // if the n is too small, just ignore it.\n    if(n <= capacity())  return;\n\n    // allocate and move old ones into the new address.\n    wy_alloc_n_move(n);\n}\n\n\n/**\n *  @brief  Resizes to the specified number of elements.\n *  @param  n  Number of elements the %vector should contain.\n *\n *  This function will resize it to the specified\n *  number of elements.  If the number is smaller than the\n *  current size it is truncated, otherwise\n *  default constructed elements are appended.\n */\n\nvoid StrVec::resize(std::size_t n)\n{\n    resize(n, std::string());\n}\n\n/**\n *  @brief  Resizes it to the specified number of elements.\n *  @param  __new_size  Number of elements it should contain.\n *  @param  __x  Data with which new elements should be populated.\n *\n *  This function will resize it to the specified\n *  number of elements.  If the number is smaller than the\n *  current size the it is truncated, otherwise\n *  the it is extended and new elements are populated with\n *  given data.\n */\nvoid StrVec::resize(std::size_t n, const std::string &s)\n{\n    if(n < size())\n    {\n        // destroy the range : [element+n, first_free) using destructor\n        for(auto p = element + n; p != first_free; /* empty */)\n            alloc.destroy(p++);\n\n        // move frist_free point to the new address element + n\n        first_free = element + n;\n    }\n    else if( n > size() )\n    {\n        for(auto i = size(); i != n; ++i)\n            push_back(std::string(s));\n    }\n}\n\n/**\n * @brief   Double the capacity and using std::move move the original strings to the newly\n *          allocated memory\n */\nvoid StrVec::reallocate()\n{\n    // calculate the new capacity required.\n    std::size_t newCapacity = size() ? 2 * size() : 1;\n\n    // allocate and move old ones into the new address.\n    wy_alloc_n_move(newCapacity);\n}\n\n/**\n * @brief   allocate new space for the given range and copy them into it\n * @param b\n * @param e\n * @return  a pair of pointers pointing to [first element , one past the last) in the new space\n */\nstd::pair<std::string *, std::string *>\nStrVec::alloc_n_copy(std::string *b, std::string *e)\n{\n    // calculate the size needed and allocate space accordingly\n    std::string* data = alloc.allocate(e - b);\n\n    return { data, std::uninitialized_copy(b, e, data) };\n    //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // which copies the range [first, last) into the space of which\n    // the starting address p_data is pointing to.\n    // This function returns a pointer pointing to one past the last element.\n}\n\n/**\n * @brief   destroy the elements and deallocate the space previously allocated.\n */\nvoid StrVec::free()\n{\n\n    if(element)     //  if not nullptr\n    {\n        // destory it  in reverse order.\n        for(auto p = first_free; p != element; /* empty */)\n            alloc.destroy(--p);\n\n        alloc.deallocate(element, capacity());\n    }\n}\n\n/**\n * @brief   allocate memory for spicified number of elements\n * @param n\n * @note    it's user's responsibility to ensure that @param n is greater than\n *          the current capacity.\n */\nvoid StrVec::wy_alloc_n_move(std::size_t n)\n{\n    std::size_t newCapacity = n;\n\n    std::string*\n            newData = alloc.allocate(newCapacity);\n\n    std::string*\n            dest    = newData;\n    std::string*\n            elem    = element;\n\n    // move the old to newly allocated space.\n    for(std::size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*elem++));\n\n    free();\n\n    // update data structure\n    element     =   newData;\n    first_free  =   dest;\n    cap         =   element + newCapacity;\n}\n"
  },
  {
    "path": "ch16/ex16.58.59/strvec.h",
    "content": "/***************************************************************************\n *  @file       strvec.h\n *  @author     Alan.W\n *  @date       05  JAN 2014\n *  @remark     16  Feb 2014 : emplace_back added\n ***************************************************************************/\n\n\n#ifndef STRVEC_H\n#define STRVEC_H\n\n#include <string>\n\n\nclass StrVec\n{\npublic:\n    // Big 3/5.\n    StrVec():\n        element(nullptr), first_free(nullptr), cap(nullptr)\n    { }\n\n    StrVec(std::initializer_list<std::string> l);\n\n\n    StrVec(const StrVec& s);\n\n    StrVec&\n    operator =(const StrVec& rhs);\n\n    ~StrVec();\n\n\n    // public members\n    void push_back(const std::string &s);\n\n    // a variadic member template using its argumenst to construct\n    // an element directly in space managed by the constainer\n    template<typename... Args>\n    void emplace_back(Args&&...);\n\n    std::size_t size() const        { return first_free - element; }\n    std::size_t capacity() const    { return cap - element; }\n\n    std::string* begin() const      { return element; }\n    std::string* end() const        { return first_free; }\n\n    // preallocate enough memory for specified number of elements\n    void reserve(std::size_t n);\n\n    // resize as required.\n    void resize(std::size_t n);\n    void resize(std::size_t n, const std::string& s);\n\n\nprivate:\n\n    // data members\n    std::string* element;       //  pointer to the first element\n    std::string* first_free;    //  pointer to the first free element\n    std::string* cap;           //  pointer to one past the end\n\n    std::allocator<std::string> alloc;\n\n    // utilities for Big 3/5\n    void reallocate();\n    void chk_n_alloc()      { if (size() == capacity()) reallocate(); }\n    void free();\n\n    // utilities added\n    // used in reallocate() reserve() and resize().\n    void wy_alloc_n_move(std::size_t n);\n\n    std::pair<std::string*, std::string*>\n    alloc_n_copy (std::string* b, std::string* e);\n\n};\n\n\n\n// call the constructors of the type to construct this element\n// and push it back.\ntemplate<typename... Args>\ninline void\nStrVec::emplace_back(Args&&... args)\n{\n    // reallocate if necessary\n    chk_n_alloc();\n    alloc.construct(first_free++, std::forward<Args>(args)...);\n}\n#endif // STRVEC_H\n"
  },
  {
    "path": "ch16/ex16.58.59/vec.h",
    "content": "/***************************************************************************\n *  @file       vec.h\n *  @author     Alan.W\n *  @date       02  FEB 2014\n *  @remark     16  Feb 2014 : emplace_back added\n ***************************************************************************/\n\n#ifndef VEC_H\n#define VEC_H\n\n#include <memory>\n\n/**\n *  @brief a vector like class\n */\ntemplate<typename T>\nclass Vec\n{\npublic:\n    Vec():element(nullptr), first_free(nullptr), cap(nullptr){ }\n    Vec(std::initializer_list<T> l);\n    Vec(const Vec& v);\n\n    Vec& operator =(const Vec& rhs);\n\n    ~Vec();\n\n    // memmbers\n    void push_back(const T& t);\n\n    template<typename... Args>\n    void emplace_back(Args&&...);\n\n    std::size_t size() const    { return first_free - element; }\n    std::size_t capacity()const { return cap - element; }\n\n    T* begin() const { return element;      }\n    T* end()   const { return first_free;   }\n\n    void reserve(std::size_t n);\n\n    void resize(std::size_t n);\n    void resize(std::size_t n, const T& t);\n\nprivate:\n    // data members\n    T* element;\n    T* first_free;\n    T* cap;\n\n    std::allocator<T> alloc;\n\n    // utillities\n    void reallocate();\n    void chk_n_alloc()  { if(size()==capacity()) reallocate(); }\n    void free();\n\n    void wy_alloc_n_move(std::size_t n);\n\n    std::pair<T*, T*> alloc_n_copy(T* b, T* e);\n};\n\n\n// copy constructor\ntemplate<typename T>\nVec<T>::Vec(const Vec &v)\n{\n    /**\n     * @brief newData is a pair of pointers pointing to newly allocated and copied\n     *        from range : [b, e)\n     */\n    std::pair<T*, T*> newData = alloc_n_copy(v.begin(), v.end());\n\n    element = newData.first;\n    first_free = cap = newData.second;\n}\n\n\n// constructor that takes initializer_list<T>\ntemplate<typename T>\nVec<T>::Vec(std::initializer_list<T> l)\n{\n    // allocate memory as large as l.size()\n    T* const newData = alloc.allocate(l.size());\n\n    // copy elements from l to the address allocated\n    T* p = newData;\n    for(const auto &t : l)\n        alloc.construct(p++, t);\n\n    // build data structure\n    element = newData;\n    first_free = cap = element + l.size();\n}\n\n\n// operator =\ntemplate<typename T>\nVec<T>& Vec<T>::operator =(const Vec& rhs)\n{\n    // allocate and copy first to protect against self_assignment\n    std::pair<T*, T*> newData = alloc_n_copy(rhs.begin(), rhs.end());\n\n    // destroy and deallocate\n    free();\n\n    // update data structure\n    element = newData.first;\n    first_free = cap = newData.second;\n\n    return *this;\n}\n\n\n// destructor\ntemplate<typename T>\nVec<T>::~Vec()\n{\n    free();\n}\n\n\n\n/**\n * @brief   allocate new memeory if nessary and push back the new T\n * @param t new T\n */\ntemplate<typename T>\nvoid Vec<T>::push_back(const T &t)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, t);\n}\n\n\ntemplate<typename T>        //for the class  template\ntemplate<typename... Args>  //for the member template\ninline void\nVec<T>::emplace_back(Args&&...args)\n{\n    chk_n_alloc();\n    alloc.construct(first_free++, std::forward<Args>(args)...);\n}\n\n\n/**\n * @brief   preallocate enough memory for specified number of elements\n * @param n number of elements required\n */\ntemplate<typename T>\nvoid Vec<T>::reserve(std::size_t n)\n{\n    // if n too small, just return without doing anything\n    if(n <= capacity()) return;\n\n    // allocate new memory and move data from old address to the new one\n    wy_alloc_n_move(n);\n}\n\n\n/**\n *  @brief  Resizes to the specified number of elements.\n *  @param  n  Number of elements the %vector should contain.\n *\n *  This function will resize it to the specified\n *  number of elements.  If the number is smaller than the\n *  current size it is truncated, otherwise\n *  default constructed elements are appended.\n */\ntemplate<typename T>\nvoid Vec<T>::resize(std::size_t n)\n{\n    resize(n, T());\n}\n\n\n\n/**\n *  @brief  Resizes it to the specified number of elements.\n *  @param  __new_size  Number of elements it should contain.\n *  @param  __x  Data with which new elements should be populated.\n *\n *  This function will resize it to the specified\n *  number of elements.  If the number is smaller than the\n *  current size the it is truncated, otherwise\n *  the it is extended and new elements are populated with\n *  given data.\n */\ntemplate<typename T>\nvoid Vec<T>::resize(std::size_t n, const T &t)\n{\n    if(n < size())\n    {\n        // destroy the range [element+n, first_free) using destructor\n        for(auto p = element + n; p != first_free;   )\n            alloc.destroy(p++);\n        // update first_free to point to the new address\n        first_free = element + n;\n    }\n    else if(n > size())\n    {\n        for (auto i = size(); i != n; ++i)\n            push_back(t);\n    }\n}\n\n\n/**\n * @brief   allocate new space for the given range and copy them into it\n * @param b\n * @param e\n * @return  a pair of pointers pointing to [first element , one past the last) in the new space\n */\ntemplate<typename T>\nstd::pair<T*, T*>\nVec<T>::alloc_n_copy(T *b, T *e)\n{\n    // calculate the size needed and allocate space accordingly\n    T* data = alloc.allocate(e-b);\n    return { data, std::uninitialized_copy(b, e, data) };\n    //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // which copies the range[first, last) to the space to which\n    // the starting address data is pointing.\n    // This function returns a pointer to one past the last element\n}\n\n\n/**\n * @brief   destroy the elements and deallocate the space previously allocated.\n */\ntemplate<typename T>\nvoid Vec<T>::free()\n{\n    // if not nullptr\n    if(element)\n    {\n        // destroy it in reverse order.\n        for(auto p = first_free; p != element;    )\n            alloc.destroy(--p);\n\n        alloc.deallocate(element, capacity());\n    }\n}\n\n\n/**\n * @brief   allocate memory for spicified number of elements\n * @param n\n * @note    it's user's responsibility to ensure that @param n is greater than\n *          the current capacity.\n */\ntemplate<typename T>\nvoid Vec<T>::wy_alloc_n_move(std::size_t n)\n{\n    // allocate as required.\n    std::size_t newCapacity = n;\n    T* newData = alloc.allocate(newCapacity);\n\n    // move the data from old place to the new one\n    T* dest = newData;\n    T* old  = element;\n    for(std::size_t i = 0; i != size(); ++i)\n        alloc.construct(dest++, std::move(*old++));\n\n    free();\n\n    // update data structure\n    element     =   newData;\n    first_free  =   dest;\n    cap         =   element + newCapacity;\n}\n\n\n/**\n * @brief   Double the capacity and using std::move move the original data to the newly\n *          allocated memory\n */\ntemplate<typename T>\nvoid Vec<T>::reallocate()\n{\n    // calculate the new capacity required\n    std::size_t newCapacity = size() ? 2 * size() : 1;\n\n    // allocate and move old data to the new space\n    wy_alloc_n_move(newCapacity);\n}\n\n\n\n#endif // VEC_H\n"
  },
  {
    "path": "ch16/ex16.6/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.6:\n// How do you think the library begin and end functions that take an array\n// argument work?\n//  std::begin  is a template function that takes a reference to an array.It\n//  returns this reference as the iterator pointing to the first element in\n//  this array.\n//\n//  std::end    is a template function that takes a reference to an array and\n//  capture the size. It return this reference plus the size as the iterator pointing\n//  to one past last element\n//\n// Define your own versions of these functions.\n//\n\n#include <iostream>\n#include <vector>\n#include <list>\n#include <string>\n\n// the same as std::begin\ntemplate<typename T, unsigned size>\nT* begin_def(T(&arr)[size])\n{\n    return arr;\n}\n\n\n// the same as std::end\ntemplate<typename T, unsigned size>\nT* end_def(T (&arr)[size])\n     ^^//We usually don't use a function name which is the same as the function of standard libary\n       ^^ //This should not be const\n{\n    return arr + size;\n}\n\nint main()\n{\n    std::string s[] = { \"sssss\",\"ss\",\"ss\",\"ssssszzzz\" };\n    std::cout << *(begin_def(s)+1) << std::endl;\n    std::cout << *(end_def(s) - 1) << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.60.61/main.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Yue Wang\n*  @date       26  Feb 2014\n*              Aug 2015\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 16.60:\n// Explain how make_shared (§ 12.1.1, p. 451) works.\n//\n//  make_shared shoudl be a variadic template function that forwards all arguments to\n//  underlying constructors that allocate and initializes an object in dynamic memory and\n//  , at last, build a shared_ptr by wrapping the raw pointer.\n//\n// Exercise 16.61:\n// Define your own version of make_shared.\n//\n\n#include <iostream>\n#include <memory>\n#include <string>\n\nnamespace ch16 //to differ from std::make_shared\n{\n    template <typename T, typename ... Args>\n    auto make_shared(Args&&... args) -> std::shared_ptr<T>\n    {\n        return std::shared_ptr<T>(new T(std::forward<Args>(args)...));\n    }\n}\n\nstruct Foo\n{\n    explicit Foo(int b) : bar(b){ }\n    int bar;\n};\n\nint main()\n{\n    auto num = ch16::make_shared<int>(42);\n    std::cout << *num << std::endl;\n\n    auto str = ch16::make_shared<std::string>(10, 'c');\n    std::cout << *str << std::endl;\n\n    auto foo = ch16::make_shared<Foo>(99);\n    std::cout << foo->bar << std::endl;\n    \n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.62/Sales_data.cc",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced.Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n * \tPearson Education, Inc.\n * \tRights and Permissions Department\n * \tOne Lake Street\n * \tUpper Saddle River, NJ  07458\n * \tFax: (201) 236-3290\n*/ \n\n#include \"Sales_data.h\"\n#include <string>\nusing std::istream;\nusing std::ostream;\n\n\nSales_data::Sales_data(istream &is) \n{\n\tis >> *this; // read a transaction from is into this object\n}\n\ndouble Sales_data::avg_price() const\n{\n\tif (units_sold)\n\t\treturn revenue/units_sold;\n\telse\n\t\treturn 0;\n}\n\n// member binary operator: left-hand operand is bound to the implicit this pointer\n// assumes that both objects refer to the same book\nSales_data& Sales_data::operator+=(const Sales_data &rhs)\n{\n\tunits_sold += rhs.units_sold;\n\trevenue += rhs.revenue;\n\treturn *this;\n}\n\n// assumes that both objects refer to the same book\nSales_data \noperator+(const Sales_data &lhs, const Sales_data &rhs)\n{\n\tSales_data sum = lhs;  // copy data members from lhs into sum\n\tsum += rhs;            // add rhs into sum\n\treturn sum;\n}\n\nistream &operator>>(istream &is, Sales_data &item)\n{\n\tdouble price;  // no need to initialize; we'll read into price before we use it\n\tis >> item.bookNo >> item.units_sold >> price;\n\tif (is)        // check that the inputs succeeded\n    \titem.revenue = item.units_sold * price;\n\telse\n    \titem = Sales_data(); // input failed: give the object the default state\n\treturn is;\n}\n\nostream &operator<<(ostream &os, const Sales_data &item)\n{\n\tos << item.isbn() << \" \" << item.units_sold << \" \" \n\t   << item.revenue << \" \" << item.avg_price();\n\treturn os;\n}\n\n// operators replace these original named functions\nistream &read(istream &is, Sales_data &item)\n{\n\tdouble price = 0;\n\tis >> item.bookNo >> item.units_sold >> price;\n\titem.revenue = price * item.units_sold;\n\treturn is;\n}\nostream &print(ostream &os, const Sales_data &item)\n{\n\tos << item.isbn() << \" \" << item.units_sold << \" \" \n\t   << item.revenue << \" \" << item.avg_price();\n\treturn os;\n}\n\t\nSales_data add(const Sales_data &lhs, const Sales_data &rhs)\n{\n\tSales_data sum = lhs;  // copy data members from lhs into sum\n\tsum += rhs;            // add rhs into sum\n\treturn sum;\n}\n\n"
  },
  {
    "path": "ch16/ex16.62/Sales_data.h",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced.Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n * \tPearson Education, Inc.\n * \tRights and Permissions Department\n * \tOne Lake Street\n * \tUpper Saddle River, NJ  07458\n * \tFax: (201) 236-3290\n*/ \n\n#ifndef SALES_DATA_H\n#define SALES_DATA_H\n\n#include <string>\n#include <iostream>\n\n\n\n// unchanged from ch14 except for added friend declaration for hash.\nclass Sales_data {\nfriend std::hash<Sales_data>;\nfriend std::ostream &operator<<\n                         (std::ostream&, const Sales_data&);\nfriend std::istream &operator>>(std::istream&, Sales_data&);\nfriend bool operator==(const Sales_data &, const Sales_data &);\n\nfriend std::ostream &print(std::ostream&, const Sales_data&);\nfriend std::istream &read(std::istream&, Sales_data&);\n\npublic:\n\t// constructors\n\tSales_data() = default;\n\tSales_data(const std::string &s): bookNo(s) { }\n\tSales_data(const std::string &s, unsigned n, double p):\n\t           bookNo(s), units_sold(n), revenue(p*n) { }\n\tSales_data(std::istream &);\n\n\tstd::string isbn() const { return bookNo; }\n\tSales_data& operator+=(const Sales_data&);\nprivate:\n\tdouble avg_price() const;  \n\tstd::string bookNo;\n\tunsigned units_sold = 0;\n\tdouble revenue = 0.0;\n};\n\n// non-member Sales_data operations\ninline\nbool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)\n{ return lhs.isbn() < rhs.isbn(); }\n\ninline\nbool operator==(const Sales_data &lhs, const Sales_data &rhs)\n{\n\treturn lhs.isbn() == rhs.isbn() && \n\t       lhs.units_sold == rhs.units_sold && \n\t       lhs.revenue == rhs.revenue;\n}\ninline\nbool operator!=(const Sales_data &lhs, const Sales_data &rhs)\n{\n\treturn !(lhs == rhs);\n}\n\n// old versions\nSales_data add(const Sales_data&, const Sales_data&);\nstd::ostream &print(std::ostream&, const Sales_data&);\nstd::istream &read(std::istream&, Sales_data&);\n\n// new operator functions\nSales_data operator+(const Sales_data&, const Sales_data&);\nstd::ostream &operator<<(std::ostream&, const Sales_data&);\nstd::istream &operator>>(std::istream&, Sales_data&);\n\n\n// specialize std::hash\n// note : template specialization should be put in the header!\nnamespace std {\ntemplate<>\nstruct hash<Sales_data>\n{\n    typedef size_t result_type;\n    typedef Sales_data argument_type;\n    size_t  operator()(const Sales_data& s) const\n    {\n        return hash<string>()(s.bookNo) ^\n                hash<unsigned>()(s.units_sold) ^\n                hash<double>()(s.revenue);\n    }\n};\n}   //std\n\n#endif\n"
  },
  {
    "path": "ch16/ex16.62/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       2  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.62:\n// Define your own version of hash<Sales_data> and define an unordered_multiset of Sales_data\n// objects. Put several transactions into the container and print its contents.\n//\n//  keep all template codes in the header.\n//\n\n#include <iostream>\n#include <memory>\n#include <unordered_set>\n#include \"Sales_data.h\"\n\nint main()\n{\n    // test for ex16.62\n    std::unordered_multiset<Sales_data> mset;\n    Sales_data sd(\"Bible\", 10, 0.98);\n\n    mset.emplace(sd);\n    mset.emplace(\"C++ Primer\", 5, 9.99);\n\n    for(const auto &item : mset)\n        std::cout << \"the hash code of \" << item.isbn()\n                  <<\":\\n0x\" << std::hex << std::hash<Sales_data>()(item)\n                  << \"\\n\";\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.63.64/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       3  Mar 2014\n *              Aug, 2015\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.63:\n// Define a function template to count the number of occurrences of a given\n// value in a vector.\n// Test your program by passing it a vector of doubles, a vector of ints,\n// and a vector of strings.\n//\n// Exercise 16.64:\n// Write a specialized version of the template from the previous exercise to\n// handle vector<const char*> and a program that uses this specialization.\n//\n\n#include <iostream>\n#include <vector>\n#include <cstring>\n\n// template\ntemplate<typename T>\nstd::size_t  count(std::vector<T> const& vec, T value) \n{\n    auto count = 0u;\n    for(auto const& elem  : vec)\n        if(value == elem) ++count;\n    return count;\n}\n\n// template specialization\ntemplate<>\nstd::size_t count (std::vector<const char*> const& vec, const char* value)\n{\n    auto count = 0u;\n    for(auto const& elem : vec)\n        if(0 == strcmp(value, elem)) ++count;\n    return count;\n}\nint main()\n{\n    // for ex16.63\n    std::vector<double> vd = { 1.1, 1.1, 2.3, 4 };\n    std::cout << count(vd, 1.1) << std::endl;\n    \n    // for ex16.64\n    std::vector<const char*> vcc = { \"alan\", \"alan\", \"alan\", \"alan\", \"moophy\" };\n    std::cout << count(vcc, \"alan\") << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.65.66.67/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       3  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.65:\n// In § 16.3 (p. 698) we defined overloaded two versions of debug_rep one\n// had a const char* and the other a char* parameter. Rewrite these functions\n// as specializations.\n//\n// Exercise 16.66:\n// What are the advantages and disadvantages of overloading\n// these debug_rep functions as compared to defining specializations?\n//\n//  Overloading changes the function match.\n//\n// Exercise 16.67:\n// Would defining these specializations affect function matching for debug_rep?\n// If so, how? If not, why not?\n//\n//  Won't change.\n//  Specializations instantiate a template; they do not overload it. As a result,\n//  specializations do not affect function matching.\n//\n\n#include <iostream>\n#include <vector>\n#include <cstring>\n#include <sstream>\n\n// template\ntemplate <typename T>\nstd::string debug_rep(T* t);\n\n// template specialization T=const char*  ,  char*  respectively.\ntemplate<>\nstd::string debug_rep(const char* str);\ntemplate<>\nstd::string debug_rep(      char *str);\n\nint main()\n{\n    char p[] = \"alan\";\n    std::cout << debug_rep(p) << \"\\n\";\n    return 0;\n}\n\n\ntemplate <typename T>\nstd::string debug_rep(T* t)\n{\n    std::ostringstream ret;\n    ret << t;\n    return ret.str();\n}\n\n// template specialization\n// T = const char*\ntemplate<>\nstd::string debug_rep(const char* str)\n{\n    std::string ret(str);\n    return str;\n}\n\n// template specialization\n// T =       char*\ntemplate<>\nstd::string debug_rep(      char *str)\n{\n    std::string ret(str);\n    return ret;\n}\n"
  },
  {
    "path": "ch16/ex16.7.8/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.7:\n// Write a constexpr template that returns the size of a given array.\n//\n// Exercise 16.8:\n// In the “Key Concept” box on page 108, we noted that as a matter of habit\n// C++ programmers prefer using != to using <. Explain the rationale for\n// this habit.\n//\n//  The reason is that more class defines \"!=\" rather than \"<\". Doing so can\n//  reduce the number of requirement of the class used with a template class.\n//\n\n#include <iostream>\n#include <vector>\n#include <list>\n#include <string>\n\ntemplate<typename T, unsigned size>\nconstexpr unsigned getSize(const T(&)[size])\n{\n    return size;\n}\n\nint main()\n{\n    std::string s[] = { \"sss\" };\n    std::cout << getSize(s) << std::endl;\n\n    char c[] = \"s\";\n    std::cout << getSize(c) << std::endl;\n    // the output is 2, as '\\0' is added at the end of the array\n    return 0;\n}\n"
  },
  {
    "path": "ch16/ex16.9.10.11/main.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Yue Wang\n *  @date       02  Feb 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 16.9:\n// What is a function template? What is a class template?\n//  A function template is a formula from which we can generate type-specific\n//  versions of that function.\n//\n//  A class template is a blueprint for generating classes. Class templates\n//  differ from function templates in that the compiler cannot deduce the\n//  template parameter type(s) for a class template. Instead, as we’ve seen\n//  many times, to use a class template we must supply additional information\n//  inside angle brackets following the template’s name (§ 3.3, p. 97).\n//\n// Exercise 16.10:\n// What happens when a class template is instantiated?\n//  The compiler uses these template arguments to instantiate a specific\n//  class from the template.\n//\n// Exercise 16.11:\n// The following definition of List is incorrect. How would you fix it?\n//  as commented below.\n//\n\ntemplate <typename elemType> class ListItem;\ntemplate <typename elemType> class List\n{\npublic:\n    List<elemType>();\n    List<elemType>(const List<elemType> &);\n    List<elemType>& operator=(const List<elemType> &);\n    ~List();\n    void insert(ListItem<elemType> *ptr, elemType value);\n    //                 ^^^^^^^^^^  -- template is not a type, the type must be provided\n\nprivate:\n    ListItem<elemType> *front, *end;\n    //      ^^^^^^^^ -- template is not a type, the type must be provided\n};\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch17/17_24.cpp",
    "content": "//exercise 17.24\n//Write your own version of the program to reformat phone numbers.\n\n\n#include <iostream>\n#include <regex>\n#include <string>\n\nusing namespace std;\n\n\nstring pattern = \"(\\\\()?(\\\\d{3})(\\\\))?([-. ])?(\\\\d{3})([-. ])?(\\\\d{4})\";\nstring format = \"$2.$5.$7\";\nregex r(pattern);\nstring s;\n\nint main()\n{\n    while(getline(cin,s))\n    {\n        cout<<regex_replace(s,r,format)<<endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch17/17_25.cpp",
    "content": "//exercise 17.25\n//Rewrite your phone program so that it writes only the first phone number for each person\n\n#include <iostream>\n#include <regex>\n#include <string>\n\nusing namespace std;\n\nstring pattern = \"(\\\\()?(\\\\d{3})(\\\\))?([-. ])?(\\\\d{3})([-. ])?(\\\\d{4})\";\nstring fmt = \"$2.$5.$7\";\nregex r(pattern);\nstring s;\n\nint main()\n{\n    while(getline(cin,s))\n    {\n        smatch result;\n        regex_search(s,result,r);\n        if(!result.empty())\n        {\n        cout<<result.prefix()<<result.format(fmt)<<endl;\n        }\n        else\n        {\n            cout<<\"Sorry, No match.\"<<endl;\n        }\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch17/17_27.cpp",
    "content": "//exercise 17.27\n//Write a program that reformats a nine-digit zip code as ddddd-dddd.\n\n#include <iostream>\n#include <regex>\n#include <string>\n\nusing namespace std;\n\nstring pattern = \"(\\\\d{5})([.- ])?(\\\\d{4})\";\nstring fmt = \"$1-$3\";\n\nregex r(pattern);\nstring s;\n\n\nint main()\n{\n    while(getline(cin,s))\n    {\n        smatch result;\n        regex_search(s,result, r);\n\n        if(!result.empty())\n        {\n            cout<<result.format(fmt)<<endl;\n        }\n        else\n        {\n            cout<<\"Sorry, No match.\"<<endl;\n        }\n\n    }\n    return 0;\n}\n"
  },
  {
    "path": "ch17/17_35_36.cpp",
    "content": "//@Squawk09\n\n//17.35 \n//Write a version of the program from page 758, that printed the square root of 2 but this time print hexadecimal digints in uppercase\n#include <iostream>\n#include <iomanip>\n#include <math.h>\nusing namespace std;\n\nint main()\n{\n\tcout <<\"default format: \" << 100 * sqrt(2.0) << '\\n'\n\t\t<< \"scientific: \" << scientific << 100 * sqrt(2.0) << '\\n'\n\t\t<< \"fixed decimal: \" << fixed << 100 * sqrt(2.0) << '\\n'\n\t\t<< \"hexidecimal: \" << uppercase << hexfloat << 100 * sqrt(2.0) << '\\n'\n\t\t<< \"use defaults: \" << defaultfloat << 100 * sqrt(2.0)\n\t\t<< \"\\n\\n\";\n}\n\n//17.36\n//Modify the program from the previous exercise to print the various floating-point values so that they line up in a column.\n#include <iostream>\n#include<iomanip>\n#include <math.h>\nusing namespace std;\n\nint main()\n{\n\tcout <<left<<setw(15) << \"default format:\" <<setw(25)<< right<< 100 * sqrt(2.0) << '\\n'\n\t<< left << setw(15) << \"scientific:\" << scientific << setw(25) << right << 100 * sqrt(2.0) << '\\n'\n\t<< left << setw(15) << \"fixed decimal:\" << setw(25) << fixed << right << 100 * sqrt(2.0) << '\\n'\n\t<< left << setw(15) << \"hexidecimal:\" << setw(25) << uppercase << hexfloat << right << 100 * sqrt(2.0) << '\\n'\n\t<< left << setw(15) << \"use defaults:\" << setw(25) << defaultfloat << right << 100 * sqrt(2.0)\n\t<< \"\\n\\n\";\n}\n"
  },
  {
    "path": "ch17/17_37_38/17_37_38.cpp",
    "content": "//@Squawk09\n\n//17.37\n//Use the unformatted version of getline to read a file a line at a time.\n//Test your program by giving it a file that contains empty lines as well as lines that are\n//longer than the character array that you pass to getline.\n\n#include <iostream>\n#include <fstream>\n#include <iomanip>\n\nusing namespace std;\n\n//int main () {\n//  ifstream myfile(\"F:\\\\Git\\\\Cpp-Primer\\\\ch17\\\\17_37_38\\\\test.txt\");\n//  if (myfile) cout << 1 << endl;\n//  char sink [250];\n//\n//  while(myfile.getline(sink,250))\n//  {\n//    cout << sink << endl;\n//  }\n//  return 0;\n//}\n\n//17.38\n//Extend your program from the previous exercise to print each word you read onto its own line.\n\n//#include <iostream>\n//#include <fstream>\n//#include <iomanip>\n//\n//using namespace std;\n//\n//int main () {\n//  ifstream myfile (\"F:\\\\Git\\\\Cpp-Primer\\\\ch17\\\\17_37_38\\\\test.txt\");\n//  char sink [250];\n//\n//  while(myfile.getline(sink,250,' '))\n//  {\n//    cout << sink << endl;\n//  }\n//  return 0;\n//}\n\n\nint main()\n{\n\tstd::cout << \"Standard Output!\\n\";\n\tstd::cerr << \"Standard Error!\\n\";\n\tstd::clog << \"Standard Log??\\n\";\n}\n"
  },
  {
    "path": "ch17/17_37_38/test.txt",
    "content": "I'm expressin' with my full capabilities,\nAnd now I'm livin' in correctional facilities,\nCause some don't agree with how I do this.\nI get straight, meditate like a Buddhist\nI'm droppin' flava, my behaviour is heriditery,\nBut my technique is very necessary.\nBlame it on Ice Cube... Because he says it gets funky\nWhen you got a subject and a predacit.\n\n\nAdd it on a dope beat\nAnd that'll make you think.\nSome suckaz just tickle me pink\nTo my stomache. 'Cause they don't flow like this one.\nYou know what? I won't hesitate to dis one\nOr two before I'm through.\nSo don't try to sing this!\nSome drop science\nWhile I'm droppin' English.\nEven if Yella\nMakes it a-capella\nI still express, yo, I don't smoke weed or a sess.\nCause its known to give a brother brain damage.\nAnd brain damage on the mic don't manage\nNuthin'\nBut makin' a sucker and you equal.\nDon't be another sequel..."
  },
  {
    "path": "ch17/data/record.txt",
    "content": "green  (9998886666 9996668888\nmorgan 2015552368 8625550123\ndrew   9735550130\nlee    6095550132 2015550175 8005550000\n"
  },
  {
    "path": "ch17/ex17.3/main.cpp",
    "content": "﻿/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       3  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 17.3:\n// Rewrite the TextQuery programs from § 12.3 (p. 484) to use a tuple instead\n// of the QueryResult class. Explain which design you think is better and why.\n//\n//  The orignal way is more formal.The second way is quick to implement , but hard to\n//  refactor.So the second way is better for testing.\n//\n\n#include <iostream>\n#include \"textquery.h\"\n\nint main()\n{\n\treturn 0;\n}\n"
  },
  {
    "path": "ch17/ex17.3/textquery.cpp",
    "content": "/***************************************************************************\n *  @file       textqueryr.cpp\n *  @author     Alan.W\n *  @date       29  DEC 2013\n *  @remark\n ***************************************************************************/\n\n#include \"textquery.h\"\n#include \"queryresult.h\"\n#include <iterator>\n#include <algorithm>\n#include <sstream>\n\n// Constructor\nTextQuery::TextQuery(std::ifstream & is) : file(new std::vector<std::string>)\n{\n    // each line\n    std::string line;\n    while(std::getline(is, line))\n    {\n        file->push_back(line);\n        // current line index\n        int index = file->size() - 1;\n\n        // for each word\n        std::stringstream lineSteam(line);\n        std::string word;\n        while(lineSteam >> word)\n        {\n            // fetch the smart pointer which is null when the word first time seen\n            std::shared_ptr<std::set<index_Tp>>& sp_lineIndex = wm[word];\n\n            // if null, allcate a new set to contain line indices\n            if(!sp_lineIndex)\n                sp_lineIndex.reset(new std::set<index_Tp>);\n\n            // insert\n            sp_lineIndex->insert(index);\n        }\n    }\n}\n\n/**\n * @brief do a query opertion and return QueryResult object.\n */\nQueryResult\nTextQuery::query(const std::string &sought) const\n{\n    // dynamicaly allocated set used for the word does not appear.\n    static std::shared_ptr<std::set<index_Tp>> noData(new std::set<index_Tp>);\n\n    // fetch the iterator to the matching element in the map<word, lines>.\n    //std::map<std::string, std::shared_ptr<std::set<index_Tp>>>::const_iterator\n    auto iter = wm.find(sought);\n    if(iter == wm.end())\n        return QueryResult(sought, noData, file);\n    else\n        return QueryResult(sought, iter->second, file);\n}\n\n/**\n * @brief do a query opertion and return tuple.\n */\nresult_tuple TextQuery::query_return_tuple(const std::string &sought)\n{\n    // dynamicaly allocated set used for the word does not appear.\n    static std::shared_ptr<std::set<index_Tp>> noData(new std::set<index_Tp>);\n\n    // fetch the iterator to the matching element in the map<word, lines>.\n    auto iter = wm.find(sought);\n    if(iter == wm.end())\n        return result_tuple(sought, noData, file);\n    else\n        return result_tuple(sought, iter->second, file);\n}\n"
  },
  {
    "path": "ch17/ex17.3/textquery.h",
    "content": "/***************************************************************************\n *  @file       textqueryr.h\n *  @author     Alan.W\n *  @date       29  DEC 2013\n *  @remark\n ***************************************************************************/\n\n#ifndef TEXTQUERY_H\n#define TEXTQUERY_H\n\n#include <vector>\n#include <string>\n#include <fstream>\n#include <memory>\n#include <map>\n#include <set>\n\nclass QueryResult;\n\nclass TextQuery\n{\npublic:\n    typedef std::vector<std::string>::size_type index_Tp;\n    typedef std::tuple <std::string, std::shared_ptr<std::set<index_Tp>>, std::shared_ptr<std::vector<std::string>>>  result_tuple;\n\n    // constructor\n    TextQuery(std::ifstream&);\n\n    // query operation returns QueryResult\n    QueryResult\n    query(const std::string&) const;\n\n    // query operation returns tuple\n    result_tuple query_return_tuple(const std::string& sought);\nprivate:\n    std::shared_ptr<std::vector<std::string>> file;\n    std::map<std::string, std::shared_ptr<std::set<index_Tp>>> wm;\n};\n\n#endif // TEXTQUERY_H\n"
  },
  {
    "path": "ch17/ex17_10.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       6  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 17.10:\n// Using the sequence 1, 2, 3, 5, 8, 13, 21, initialize a bitset that has a\n// 1 bit in each position corresponding to a number in this sequence. Default\n// initialize another bitset and write a small program to turn on each of the\n// appropriate bits.\n//\n\n\n\n#include <iostream>\n#include <bitset>\n#include <vector>\n\nint main()\n{\n    std::vector<int> v = { 1, 2, 3, 5, 8, 13, 21 };\n    std::bitset<32> bset;\n\n    for (auto i : v)    bset.set(i);\n\n    std::bitset<32> bset2;\n    for (unsigned i = 0; i != 32; ++i)\n        bset2[i] = bset[i];\n\n    std::cout <<bset <<std::endl;\n    std::cout <<bset2<<std::endl;\n}\n"
  },
  {
    "path": "ch17/ex17_11_12_13.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     gau fung\n*  @date       25  May 2015\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 17.11:\n// Define a data structure that contains an integral object to track responses\n// to a true/false quiz containing 10 questions. What changes, if any, would\n// you need to make in your data structure if the quiz had 100 questions?\n//\n// Exercise 17.12:\n// Using the data structure from the previous question, write a function that\n// takes a question number and a value to indicate a true/false answer and\n// updates the quiz results accordingly.\n//\n// Exercise 17.13:\n// Write an integral object that contains the correct answers for the\n// true/false quiz. Use it to generate grades on the quiz for the data\n// structure from the previous two exercises.\n//\n\n#ifndef QUIZ\n#define QUIZ\n#include <iostream>\n#include <bitset>\n#include <utility>\n#include <string>\n#include <iostream>\n\n//class Quiz\ntemplate<std::size_t N>\nclass Quiz\n{\npublic:\n    //constructors\n    Quiz() = default;\n    Quiz(std::string& s) :bitquiz(s){ }\n\n    //generate grade\n    template<std::size_t M>\n    friend std::size_t grade(Quiz<M> const&, Quiz<M> const&);\n\n    //print\n    template<std::size_t M>\n    friend std::ostream& operator<<(std::ostream&, Quiz<M> const&);\n\n    //update bitset\n    void update(std::pair<std::size_t, bool>);\nprivate:\n    std::bitset<N> bitquiz;\n};\n#endif\n\ntemplate<std::size_t N>\nvoid Quiz<N>::update(std::pair<std::size_t, bool> pair)\n{\n    bitquiz.set(pair.first, pair.second);\n}\n\ntemplate<std::size_t M>\nstd::ostream& operator<<(std::ostream& os, Quiz<M> const& quiz)\n{\n    os << quiz.bitquiz;\n    return os;\n}\n\ntemplate<std::size_t M>\nstd::size_t grade(Quiz<M> const& corAns, Quiz<M> const& stuAns)\n{\n    auto result = stuAns.bitquiz ^ corAns.bitquiz;\n    result.flip();\n    return result.count();\n}\n\n\nint main()\n{\n    //Ex17_11\n    std::string s = \"1010101\";\n    Quiz<10> quiz(s);\n    std::cout << quiz << std::endl;\n\n    //EX17_12\n    quiz.update(std::make_pair(1, true));\n    std::cout << quiz << std::endl;\n\n    //Ex17_13\n    std::string answer = \"10011\";\n    std::string stu_answer = \"11001\";\n    Quiz<5> ans(answer), stu_ans(stu_answer);\n    std::cout << grade(ans, stu_ans) << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch17/ex17_14_15_16.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Queequeg\n *  @date       19  Nov 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note       There are some bugs in gcc(include the latest version 4.9.2) \n *              to handle regular expression.To compile this program, please\n *\t\t\t    turn to other compilers such as msvs2013 and clang.\n ***************************************************************************/\n//\n// Exercise 17.14\n// Write several regular expressions designed to trigger various errors.\n// Run your program to see what output your compiler generates for each error.\n\n// Exercise 17.15\n// Write  a program using the pattern that finds word that violate the\n// \"i before e except after c\" rule. Have your program prompt the user to\n// supply a word and indicate whether the word is okay or not. Test your\n// program with words that do and do not violate the rule.\n\n// Exercise 17.16\n// What would happen if your regex object in the previous program were\n// initialized with \"[^c]ei\"? Test your program using that pattern to see\n// whether your expectations were correct.\n\n\n#include <iostream>\nusing std::cout;\nusing std::cin;\nusing std::endl;\n\n#include <string>\nusing std::string;\n\n#include <regex>\nusing std::regex;\nusing std::regex_error;\n\nint main()\n{\n    // for ex17.14\n    // error_brack\n    try{\n        regex r(\"[[:alnum:]+\\\\.(cpp|cxx|cc)$\", regex::icase);\n    }\n    catch(regex_error e)\n    {\n        cout << e.what() << \" code: \" << e.code() << endl;\n    }\n\n    // for ex17.15\n    regex r(\"[[:alpha:]]*[^c]ei[[:alpha:]]*\", regex::icase);\n    string s;\n    cout << \"Please input a word! Input 'q' to quit!\" << endl;\n    while(cin >> s && s != \"q\")\n    {\n        if(std::regex_match(s, r))\n            cout << \"Input word \" << s << \" is okay!\" << endl;\n        else\n            cout << \"Input word \" << s << \" is not okay!\" <<endl;\n\n        cout << \"Please input a word! Input 'q' to quit!\" << endl;\n    }\n\n    cout << endl;\n\n    // for ex17.16\n    r.assign(\"[^c]ei\", regex::icase);\n    cout << \"Please input a word! Input 'q' to quit!\" << endl;\n    while(cin >> s && s != \"q\")\n    {\n        if(std::regex_match(s, r))\n            cout << \"Input word \" << s << \" is okay!\" << endl;\n        else\n            cout << \"Input word \" << s << \" is not okay!\" <<endl;\n\n        cout << \"Please input a word! Input 'q' to quit!\" << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "ch17/ex17_17_18.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Queequeg\n*  @date       25  Nov 2014\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note       There are some bugs in gcc(include the latest version 4.9.2)\n*              to handle regular expression.To compile this program, please\n*\t\t\t   turn to other compilers such as msvs2013 and clang.\n***************************************************************************/\n//\n// Exercise 17.17\n// Update your program so that it finds all the words in an input sequence\n// that violiate the \"ei\" grammar rule.\n\n//\n// Exercise 17.18\n// Revise your program to ignore words that contain \"ei\" but are not \n// misspellings, such as \"albeit\" and \"neighbor.\"\n\n#include <iostream>\nusing std::cout;\nusing std::cin;\nusing std::endl;\n\n#include <string>\nusing std::string;\n\n#include <regex>\nusing std::regex;\nusing std::sregex_iterator;\n\nint main()\n{\n\tstring s;\n\tcout << \"Please input a sequence of words:\" << endl;\n\tgetline(cin, s);\n\tcout << endl;\n\tcout << \"Word(s) that violiate the \\\"ei\\\" grammar rule:\" << endl;\n\tstring pattern(\"[^c]ei\");\n\tpattern = \"[[:alpha:]]*\" + pattern + \"[[:alpha:]]*\";\n\tregex r(pattern, regex::icase);\n\tfor (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it)\n\t\tcout << it->str() << endl;\n\n\treturn 0;\n}\n"
  },
  {
    "path": "ch17/ex17_19_20.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Queequeg\n*  @date       26  Nov 2014\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note       There are some bugs in gcc(include the latest version 4.9.2) \n*              to handle regular expression.To compile this program, please\n*\t\t\t   turn to other compilers such as msvs2013 and clang.\n***************************************************************************/\n//\n// Exercise 17.19\n// Why is it okay to call m[4].str() without first checking whether m[4] \n// was matched?\n// We expect that the two delimiters in m[4] and m[6] are the same. \n// If m[4](or m[6]) is mismatched, m[4].str()(or m[6].str() respectively) \n// returns an empty string which can also be compared with the other\n// delimiter. \n\n//\n// Exercise 17.20\n// Write your own version of the program to validate phone numbers.\n\n#include <iostream>\nusing std::cout;\nusing std::cin;\nusing std::endl;\n\n#include <string>\nusing std::string;\n\n#include <regex>\nusing std::regex;\nusing std::sregex_iterator;\nusing std::smatch;\n\nbool valid(const smatch& m);\n\nint main()\n{\n\tstring phone = \"(\\\\()?(\\\\d{ 3 })(\\\\))?([-. ])?(\\\\d{ 3 })([-. ]?)(\\\\d{ 4 })\";\n\tregex r(phone);\n\tsmatch m;\n\tstring s;\n\tbool valid_record;\n\t// read each record from the input file\n\twhile (getline(cin, s))\n\t{\n\t\tvalid_record = false;\n\t\t// for each matching phone number\n\t\tfor (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it)\n\t\t{\n\t\t\tvalid_record = true;\n\t\t\t// check whether the number's formatting is valid\n\t\t\tif (valid(*it))\n\t\t\t\tcout << \"valid phone number: \" << it->str() << endl;\n\t\t\telse\n\t\t\t\tcout << \"invalid phone number: \" << it->str() << endl;\n\t\t}\n\n\t\tif (!valid_record)\n\t\t\tcout << \"invalid record!\" << endl;\n\t}\n\treturn 0;\n}\n\nbool valid(const smatch& m)\n{\n\t// if there is an open parenthesis before the area code\n\tif (m[1].matched)\n\t\t// the area code must be followed by a close parenthesis\n\t\t// and followed immediately by the rest of the number or a space\n\t\treturn m[3].matched && (m[4].matched == 0 || m[4].str() == \" \");\n\telse\n\t\t// then there can't be a close after the area code\n\t\t// the delimiters between the other two components must match\n\t\treturn !m[3].matched && m[4].str() == m[6].str();\n}\n"
  },
  {
    "path": "ch17/ex17_1_2.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Yue Wang\n*  @date       3  Mar 2014\n                  Jun 2015   \n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 17.1:\n// Define a tuple that holds three int values and initialize the members to 10, 20, and 30.\n//\n// Exercise 17.2:\n// Define a tuple that holds a string, a vector<string>, and a pair<string, int>.\n//\n\n#include <tuple>\n#include <string>\n#include <vector>\n\nint main()\n{\n    auto three_ints = std::make_tuple(10, 20, 30);\n    \n    using SomeTuple = std::tuple < std::string, std::vector<std::string>, std::pair<std::string, int> > ;\n    SomeTuple some_tuple;\n\n    return 0;\n}\n"
  },
  {
    "path": "ch17/ex17_21.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Queequeg\n*  @date       26  Nov 2014\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 17.21\n// Rewrite your phone number program from 8.3.2 (p. 323) to use the \n// valid function defined in this section.\n\n#include <iostream>\nusing std::cerr;\nusing std::cout;\nusing std::cin;\nusing std::endl;\nusing std::istream;\nusing std::ostream;\n\n#include <fstream>\nusing std::ifstream;\nusing std::ofstream;\n\n#include <sstream>\nusing std::istringstream;\nusing std::ostringstream;\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include <regex>\nusing std::regex;\nusing std::sregex_iterator;\nusing std::smatch;\n\nstruct PersonInfo\n{\n    string name;\n    vector<string> phones;\n};\n\nbool valid(const smatch& m);\nbool read_record(istream& is, vector<PersonInfo>& people);\nvoid format_record(ostream& os, const vector<PersonInfo>& people);\n\n// fake function that makes the program compile\nstring format(const string &num) { return num; }\n\nint main()\n{\n    vector<PersonInfo> people;\n\n    string filename;\n    cout << \"Please input a record file name: \";\n    cin >> filename;\n    cout << endl;\n    ifstream fin(filename);\n\n    if (read_record(fin, people))\n    {\n        ofstream fout(\"data\\\\result.txt\", ofstream::trunc);\n        format_record(fout, people);\n    }\n    else\n    {\n        cout << \"Fail to open file \" << filename << endl;\n    }\n\n    return 0;\n}\n\nbool valid(const smatch& m)\n{\n    // if there is an open parenthesis before the area code\n    if (m[1].matched)\n        // the area code must be followed by a close parenthesis\n        // and followed immediately by the rest of the number or a space\n        return m[3].matched && (m[4].matched == 0 || m[4].str() == \" \");\n    else\n        // then there can't be a close after the area code\n        // the delimiters between the other two components must match\n        return !m[3].matched && m[4].str() == m[6].str();\n}\n\nbool read_record(istream& is, vector<PersonInfo>& people)\n{\n    if (is)\n    {\n        string line, word; // will hold a line and word from input, respectively\n                           // read the input a line at a time until cin hits end-of-file (or another error)\n        while (getline(is, line))\n        {\n            PersonInfo info; // create an object to hold this record's data\n            istringstream record(line); // bind record to the line we just read\n            record >> info.name; // read the name\n            while (record >> word) // read the phone numbers\n                info.phones.push_back(word); // and store them\n            people.push_back(info); // append this record to people\n        }\n        return true;\n    }\n    else\n        return false;\n}\n\nvoid format_record(ostream& os, const vector<PersonInfo>& people)\n{\n    string phone = \"(\\\\()?(\\\\d{ 3 })(\\\\))?([-. ])?(\\\\d{ 3 })([-. ]?)(\\\\d{ 4 })\";\n    regex r(phone);\n    smatch m;\n\n    for (const auto &entry : people)\n    {\n        // for each entry in people\n        ostringstream formatted, badNums; // objects created on each loop\n        for (const auto &nums : entry.phones)\n        {\n            for (sregex_iterator it(nums.begin(), nums.end(), r), end_it; it != end_it; ++it)\n            {\n                // for each number\n                // check whether the number's formatting is valid\n                if (!valid(*it))\n                    // string in badNums\n                    badNums << \" \" << nums;\n                else\n                    // \"writes\" to formatted's string\n                    formatted << \" \" << format(nums);\n            }\n        }\n\n        if (badNums.str().empty()) // there were no bad numbers\n            os << entry.name << \" \" // print the name\n            << formatted.str() << endl; // and reformatted numbers\n        else // otherwise, print the name and bad numbers\n            cerr << \"input error: \" << entry.name\n            << \" invalid number(s) \" << badNums.str() << endl;\n    }\n}\n"
  },
  {
    "path": "ch17/ex17_23.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     Queequeg\n*  @date       26  Nov 2014\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n//\n// Exercise 17.23\n\n\n#include <iostream>\nusing std::cout;\nusing std::cin;\nusing std::endl;\n\n#include<string>\nusing std::string;\n\n#include <regex>\nusing std::regex;\nusing std::sregex_iterator;\nusing std::smatch;\n\nbool valid(const smatch& m);\n\nint main()\n{\n\tstring zipcode =\n\t\t\"(\\\\d{5})([-])?(\\\\d{4})?\\\\b\";\n\tregex r(zipcode);\n\tsmatch m;\n\tstring s;\n\t\n\twhile (getline(cin, s))\n\t{\n\n\t\t//! for each matching zipcode number\n\t\tfor (sregex_iterator it(s.begin(), s.end(), r), end_it;\n\t\t\tit != end_it; ++it)\n\t\t{\n\t\t\t//! check whether the number's formatting is valid\n\t\t\tif (valid(*it))\n\t\t\t\tcout << \"valid zipcode number: \" << it->str() << endl;\n\t\t\telse\n\t\t\t\tcout << \"invalid zipcode number: \" << s << endl;\n\t\t}\n\n\t}\n\treturn 0;\n}\n\nbool valid(const smatch& m)\n{\n\t\n\tif ((m[2].matched)&&(!m[3].matched))\n\t\treturn false;\n\telse\n\t\treturn true;\n}\n"
  },
  {
    "path": "ch17/ex17_28_29_30.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       7  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 17.28:\n// Write a function that generates and returns a uniformly distributed random\n// unsigned int each time it is called.\n//\n// Exercise 17.29:\n// Allow the user to supply a seed as an optional argument to the function you\n// wrote in the previous exercise.\n//\n// Exercise 17.30:\n// Revise your function again this time to take a minimum and maximum value for\n// the numbers that the function should return.\n//\n\n#include <iostream>\n#include <random>\n#include<string>\n\n// default version\nunsigned random_gen();\n// with seed spicified\nunsigned random_gen(unsigned seed);\n// with seed and range spicified\nunsigned random_gen(unsigned seed, unsigned min, unsigned max);\nint main()\n{\n    std::string temp;\n    while(std::cin >> temp)\n    std::cout << std::hex << random_gen(19, 1, 10) << std::endl;\n    return 0;\n}\n\nunsigned random_gen()\n{\n    static std::default_random_engine e;\n    static std::uniform_int_distribution<unsigned> ud;\n    return ud(e);\n}\n\nunsigned random_gen(unsigned seed)\n{\n    static std::default_random_engine e(seed);\n    static std::uniform_int_distribution<unsigned> ud;\n    return ud(e);\n}\n\nunsigned random_gen(unsigned seed, unsigned min, unsigned max)\n{\n    static std::default_random_engine e(seed);\n    static std::uniform_int_distribution<unsigned> ud(min, max);\n    return ud(e);\n}\n"
  },
  {
    "path": "ch17/ex17_33.cpp",
    "content": "/***************************************************************************\n*  @file       main.cpp\n*  @author     qwert2603\n*  @date       13 Apr 2015\n*  @remark     This code is for the exercises from C++ Primer 5th Edition\n*  @note\n***************************************************************************/\n\n#include <iostream>\nusing std::cout;\nusing std::endl;\n\n#include <fstream>\nusing std::ifstream;\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include <random>\nusing std::default_random_engine;\nusing std::uniform_int_distribution;\n\n#include <ctime>\nusing std::time;\n\n#include <algorithm>\nusing std::sort;\nusing std::find_if;\n\n#include <utility>\nusing std::pair;\n\n\nint main() {\n\ttypedef pair<string, string> ps;\n\tifstream i(\"d.txt\");\n\tvector<ps> dict;\n\tstring str1, str2;\n\t// read wirds from dictionary\n\twhile (i >> str1 >> str2) {\n\t\tdict.emplace_back(str1, str2);\n\t}\n\ti.close();\n\t// sort words in vector\n\tsort(dict.begin(), dict.end(), [](const ps &_ps1, const ps &_ps2){ return _ps1.first < _ps2.first; });\n\ti.open(\"i.txt\");\n\tdefault_random_engine e((unsigned int)(time(0)));\n\t// read words from text\n\twhile (i >> str1) {\n\t  // find word in dictionary\n\t\tvector<ps>::const_iterator it = find_if(dict.cbegin(), dict.cend(),\n\t\t  [&str1](const ps &_ps){ return _ps.first == str1; });\n\t\t// if word doesn't exist in dictionary\n\t\tif (it == dict.cend()) {\n\t\t  // write it itself\n\t\t\tcout << str1 << ' ';\n\t\t}\n\t\telse {\n\t\t  // get random meaning of word \n\t\t\tuniform_int_distribution<unsigned> u (0, find_if(dict.cbegin(), dict.cend(),\n\t\t\t [&str1](const ps &_ps){ return _ps.first > str1; }) - it - 1);\n\t\t\t// write random meaning\n\t\t\tcout << (it + u(e))->second << ' ';\n\t\t}\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "ch17/ex17_4_5_6_7_8.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       3  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 17.4:\n// Write and test your own version of the findBook function.\n//\n// Exercise 17.5:\n// Rewrite findBook to return a pair that holds an index and a pair of iterators.\n//\n// Exercise 17.6:\n// Rewrite findBook so that it does not use tuple or pair.\n//\n// Exercise 17.7:\n// Explain which version of findBook you prefer and why.\n//\n//  The version using tuple is prefered.It's more flexible, campared to other versions.\n//\n// Exercise 17.8:\n// What would happen if we passed Sales_data() as the third parameter to accumulate\n// in the last code example in this section?\n//\n//  If so, the output should be 0, as the Sales_data is default constructed.\n//\n\n\n\n#include <iostream>\n#include <tuple>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <utility>\n#include <numeric>\n\n#include \"ex17_4_5_6_7_8_SalesData.h\"\n\n// for ex17.4\n// maches has 3 members:\n// an index of a store and iterators into that store's vector\ntypedef std::tuple<std::vector<Sales_data>::size_type,\n                   std::vector<Sales_data>::const_iterator,\n                   std::vector<Sales_data>::const_iterator>\n                                                            matches;\n\n// for ex17.5\n// return a pair that holds an index and a pair of iterators.\ntypedef std::pair<std::vector<Sales_data>::size_type,\n                  std::pair<std::vector<Sales_data>::const_iterator,\n                            std::vector<Sales_data>::const_iterator>>\n                                                                      matches_pair;\n\n// for ex17.6\n// return a struct that holds an index of a store and iterators into that store's vector\nstruct matches_struct\n{\n    std::vector<Sales_data>::size_type st;\n    std::vector<Sales_data>::const_iterator first;\n    std::vector<Sales_data>::const_iterator last;\n    matches_struct(std::vector<Sales_data>::size_type s,\n                   std::vector<Sales_data>::const_iterator f,\n                   std::vector<Sales_data>::const_iterator l) : st(s), first(f), last(l) { }\n} ;\n\n// for ex17.4\n// return a vector with an entry for each store that sold the given book.\nstd::vector<matches>\nfindBook(const std::vector<std::vector<Sales_data>>& files,\n         const std::string& book);\n\n// print the result using the given iostream\nvoid reportResults(std::istream& in, std::ostream os,\n                   const std::vector<std::vector<Sales_data>>& files);\n\n// for ex17.5\n// return a vector with an entry for each store that sold the given book.\nstd::vector<matches_pair>\nfindBook_pair(const std::vector<std::vector<Sales_data> > &files,\n              const std::string &book);\n\n// for ex17.6\n// return a vector with an entry for each store that sold the given book.\nstd::vector<matches_struct>\nfindBook_struct(const std::vector<std::vector<Sales_data> > &files,\n                const std::string &book);\n\nint main()\n{\n    return 0;\n}\n\n// for ex17.4\n// return a vector with an entry for each store that sold the given book.\nstd::vector<matches>\nfindBook(const std::vector<std::vector<Sales_data>>& files,\n         const std::string& book)\n{\n    std::vector<matches> ret;\n\n    // for each strore find the range of matching books, if any\n    for (auto it = files.cbegin(); it != files.cend(); ++it)\n    {\n        // find the range of Sales_data tat have the same ISBN\n        auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);\n        if(found.first != found.second)\n            ret.push_back(std::make_tuple(it - files.cbegin(),\n                                          found.first, found.second));\n    }\n    return ret;\n}\n\n// for ex17.4\n// print the result using the given iostream\nvoid reportResults(std::istream& in, std::ostream os,\n                   const std::vector<std::vector<Sales_data>>& files)\n{\n    std::string s;\n    while(in >> s)\n    {\n        auto trans = findBook(files, s);\n        if(trans.empty()){\n            std::cout << s << \"not found in any stores\" << std::endl;\n            continue;\n        }\n\n        for(const auto& store :trans)\n            os << \"store \" << std::get<0>(store) << \" sales: \"\n               << std::accumulate(std::get<1>(store), std::get<2>(store),\n                                  Sales_data(s))\n                  << std::endl;\n    }\n}\n\n// for ex17.5\n// return a vector with an entry for each store that sold the given book\nstd::vector<matches_pair>\nfindBook_pair(const std::vector<std::vector<Sales_data> > &files,\n              const std::string &book)\n{\n    std::vector<matches_pair> ret;\n    for(auto it = files.cbegin(); it != files.cend(); ++it)\n    {\n        auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);\n        if(found.first != found.second)\n            ret.push_back(std::make_pair(it - files.cbegin(),\n                                         std::make_pair(found.first, found.second)));\n    }\n    return ret;\n}\n\n// for ex17.6\n// return a vector with an entry for each store that sold the given book.\nstd::vector<matches_struct>\nfindBook_struct(const std::vector<std::vector<Sales_data> > &files,\n                const std::string &book)\n{\n    std::vector<matches_struct> ret;\n    for(auto it = files.cbegin(); it != files.cend(); ++it)\n    {\n        auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);\n        if(found.first != found.second)\n            ret.push_back(matches_struct(it - files.cbegin(), found.first, found.second));\n    }\n    return ret;\n}\n"
  },
  {
    "path": "ch17/ex17_4_5_6_7_8_SalesData.cpp",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced.Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n * \tPearson Education, Inc.\n * \tRights and Permissions Department\n * \tOne Lake Street\n * \tUpper Saddle River, NJ  07458\n * \tFax: (201) 236-3290\n*/ \n\n\n#include <iostream>\nusing std::istream; using std::ostream;\n\n#include \"ex17_4_5_6_7_8_SalesData.h\"\n\nSales_data::Sales_data(std::istream &is) \n{\n\t// read will read a transaction from is into this object\n\tread(is, *this);\n}\n\ndouble \nSales_data::avg_price() const {\n\tif (units_sold)\n\t\treturn revenue/units_sold;\n\telse\n\t\treturn 0;\n}\n\n// add the value of the given Sales_data into this object\nSales_data& \nSales_data::combine(const Sales_data &rhs)\n{\n\tunits_sold += rhs.units_sold; // add the members of rhs into \n\trevenue += rhs.revenue;       // the members of ``this'' object\n    return *this; // return the object on which the function was called\n}\n// = Sales_data\nSales_data &Sales_data::operator =(const Sales_data &rhs)\n{\n    this->bookNo        = rhs.bookNo;\n    this->revenue       = rhs.revenue;\n    this->units_sold    = rhs.units_sold;\n\n    return *this;\n}\n\n// =string\nSales_data &Sales_data::operator =(const std::string &rhs)\n{\n    *this= Sales_data(rhs);\n    return *this;\n}\n\n// +=\nSales_data &Sales_data::operator +=(const Sales_data &rhs)\n{\n    this->revenue += rhs.revenue;\n    this->units_sold += rhs.units_sold;\n\n    return *this;\n}\n\nSales_data \nadd(const Sales_data &lhs, const Sales_data &rhs)\n{\n\tSales_data sum = lhs;  // copy data members from lhs into sum\n\tsum.combine(rhs);      // add data members from rhs into sum\n\treturn sum;\n}\n\n// transactions contain ISBN, number of copies sold, and sales price\nistream&\nread(istream &is, Sales_data &item)\n{\n\tdouble price = 0;\n\tis >> item.bookNo >> item.units_sold >> price;\n\titem.revenue = price * item.units_sold;\n\treturn is;\n}\n\nostream&\nprint(ostream &os, const Sales_data &item)\n{\n\tos << item.isbn() << \" \" << item.units_sold << \" \" \n\t   << item.revenue << \" \" << item.avg_price();\n\treturn os;\n}\n\n// added 10.Jan 2014\nstd::ostream &\noperator <<(std::ostream &os, const Sales_data &item)\n{\n    os << item.isbn() << \" \" << item.units_sold << \" \"\n       << item.revenue << \" \" << item.avg_price();\n\n    return os;\n}\n\n// added 12.Jan 2014\nstd::istream&\noperator >>(std::istream &is, Sales_data &s)\n{\n    double price;\n\n    // read input\n    is >> s.bookNo >> s.units_sold >> price;\n\n    // if successful, write into the object, give the object default state otherwise.\n    if(is)\n        s.revenue = s.units_sold * price;\n    else\n        s = Sales_data();\n\n    return is;\n}\n"
  },
  {
    "path": "ch17/ex17_4_5_6_7_8_SalesData.h",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced.Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n * \tPearson Education, Inc.\n * \tRights and Permissions Department\n * \tOne Lake Street\n * \tUpper Saddle River, NJ  07458\n * \tFax: (201) 236-3290\n*/ \n\n//\n// Exercise 14.45:\n// Write conversion operators to convert a Sales_data to string and to double.\n// What values do you think these operators should return?\n//\n#ifndef SALES_DATA_H\n#define SALES_DATA_H\n\n#include <string>\n#include <iostream>\n\n\nclass Sales_data\n{\n    // friends\n    friend Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs);\n\n    friend std::ostream&\n    operator << (std::ostream& os, const Sales_data& s);\n\n    friend std::istream&\n    operator >> (std::istream& is, Sales_data& s);\n\n    friend Sales_data add(const Sales_data&, const Sales_data&);\n    friend std::ostream &print(std::ostream&, const Sales_data&);\n    friend std::istream &read(std::istream&, Sales_data&);\n\npublic:\n\t// constructors\n\tSales_data() = default;\n\tSales_data(const std::string &s): bookNo(s) { }\n\tSales_data(const std::string &s, unsigned n, double p):\n\t           bookNo(s), units_sold(n), revenue(p*n) { }\n    Sales_data(const Sales_data &s ):\n        bookNo(s.bookNo), units_sold(s.units_sold), revenue(s.revenue)\n    { }\n\n    Sales_data(Sales_data&& s):\n        bookNo(s.bookNo), units_sold(s.units_sold), revenue(s.revenue)\n    { }\n\n    ~Sales_data(){ }\n\tSales_data(std::istream &);\n\n\tstd::string isbn() const { return bookNo; }\n\tSales_data& combine(const Sales_data&);\n\n    // assignments\n    Sales_data& operator  =(const Sales_data& rhs);\n    Sales_data& operator  =(const std::string&  rhs);\n    Sales_data& operator +=(const Sales_data& rhs);\n\n    // conversion\n    explicit operator std::string () const { return bookNo; }\n    explicit operator double      () const { return revenue; }\n\n\tdouble avg_price() const;\nprivate:\n\tstd::string bookNo;\n\tunsigned units_sold = 0;\n\tdouble revenue = 0.0;\n};\n\n\n// overloaded operators added 10.Jan.2014 for ex14.2\ninline Sales_data\noperator+(const Sales_data& lhs, const Sales_data& rhs)\n{\n    Sales_data sum = lhs;\n    sum += rhs;\n\n    return sum;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const Sales_data& item);\n\nstd::istream&\noperator >> (std::istream& is, Sales_data& s);\n\n// nonmember Sales_data interface functions\nSales_data add(const Sales_data&, const Sales_data&);\nstd::ostream &print(std::ostream&, const Sales_data&);\nstd::istream &read(std::istream&, Sales_data&);\n\n// used in future chapters\ninline \nbool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)\n{\n\treturn lhs.isbn() < rhs.isbn();\n}\n#endif\n"
  },
  {
    "path": "ch17/ex17_9.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       3  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 17.9: Explain the bit pattern each of the following bitset objects contains:\n//     (a) bitset<64> bitvec(32);\n//          0000000000000000000000000000000000000000000000000000000000100000\n//                                      //                           ^\n//     (b) bitset<32> bv(1010101);\n//          00000000000011110110100110110101\n//          // note that the argument here is decemal\n//     (c) string bstr; cin >> bstr; bitset<8>bv(bstr);\n//          depends on what has been input.\n//\n\n\n\n#include <iostream>\n#include <bitset>\n\n//#include \"Sales_data.h\"\n\n\nint main()\n{\n    std::bitset<32> bv(1010101);\n\n    std::cout << bv << std::endl;\n}\n"
  },
  {
    "path": "ch18/18_18 18_19.cpp",
    "content": "//@Squawk09\n\n//18.18\n//Given the following typical definition of swap 13.3 (p.157) determine which version of swap is used\n//if mem1 is a string. What if mem1 is an int?\n//Explain how name lookup works in both cases.\n\nvoid swap(T v1,Tv2)\n{\n    using std::swap;\n    swap(vq.mem1,v2.mem1);\n    //swap remaining members of type T\n}\n\n//Swap is a template function defined by the standard library.\n//By stating we are using std::swap all the following uses of swap in the scope of the function will\n//look for the matching template for its argument types in the standard library.\n//If mem1 is a string the program will use the standard library function that has string arguments.\n//If mem1 is int, it will use the standard library template version with int arguments.\n\n\n//18.19\n//What if the call to swap was std::swap(v1.mem1,v2.mem1);\n\n//The function would use the matching std version of swap for that specific call.\n//It would not necessarily use the matching standard library version of swap for the following calls.\n"
  },
  {
    "path": "ch18/18_20.cpp",
    "content": "//@Squawk09\n\n//Exercise 18.20\n//In the following code, determine which function, if any, matches the call to compute, List the candidate and viable functions.\n//What type conversions, if any, are applied to the argument to match the parameter in each viable function.\n\n//void compute(int) first, no type conversion\n\n//void const void works.\n//void compute() doesn't work\n//double double works converted to double\n//char char works\n#include<iostream>\n\nnamespace primerLib {\n    void compute();  //Error, does not work. Too many argument in the call to match.\n\tvoid compute(const void *) { }; //Works! Converts argument to a constant void pointer.\n}\n\nvoid compute(int) { std::cout << \"compute(int)\" << std::endl; };//Works! Most closely matches the argument parameters so it is selected first.\nvoid compute(double, double =3.4);//Works! Converts argument to double.\nvoid compute(char* x,char* =0);//Works! converts to a character pointer.\n\nvoid f()\n{\n\tusing primerLib::compute;\n    compute(0);\n}\n\nint main()\n{\n\tf();\n    return 0;\n}\n\n//What would happen if using declaration were located in main before the call to compute?\n//Answer the same questions as before.\n\n//The compiler will match to void compute( const void *) in the primerLib namespace.\n//void compute() will still not work because of too many arguments.\n"
  },
  {
    "path": "ch18/README.md",
    "content": "## Exercise 18.1\n\n> What is the type of the exception object in the following throws?\n> \n> **(a)**`range_error r(\"error\");`\n> `throw r`;\n> **(b)**`exception *p = &r;`\n> `throw *P;`\n\n>What would happen if the `throw` in **(b)** were written as `throw p`?\n\n\tThe type of the exception object in (a) is range_error which is used to report range errors in internal computations.\n\tThe type of the exception object in (b) is exception.\n\tIf the \"throw\" in (b) were written as \"throw p\", there will be a runtime error.\n\n\n## Exercise 18.2\n\n> Explain what happens if an exception occurs at the indicated point:\n\n\n```cpp\nvoid exercise(int *b, int *e)\n{\n\tvector<int> v(b, e);\n\tint *p = new int[v.size()];\n\tifstream in(\"ints\");\n\t// exception occurs here\n}\n```\n\nThe space \"p\" points will not be free. There will be a memory leak.\n\n## Exercise 18.3\n\n## Exercise 18.21\n\n>Explain the following declarations. Identify any that are in error and explain why they are incorrect:\n\n>**(a)**\n```cpp\nclass CAD{};\nclass Vehicle{};\nclass CADVehicle : public CAD, Vehicle{};\n```\n\n\nCAD Vehicle publicly inherits from CAD and privaetely inherits from Vehicle.  CADVehicle gets\nall the  public and private methods that Vehicle has but cant be cast to a Vehicle argument.\nIt is an \"inaccessible\" base.\nfor example\n\n```cpp\nCadVehicle example;\n\nvoid foo(Vehicle){/*do something*/};\n\nfoo(CADVehicle);//will not work, will work if Vehicle were public\n```\n\n>**(b)**\n```cpp\nclass DBList: public List,public List {/*do something*/};\n```\n\nError because you are trying to derive from the same base class twice.  If two different \nlibraries or header files define the same named class,you need to specify with\na scope resolution operator, i.e. headerfile_name::List.\n\n>**(c)**\n```cpp\nclass iostream : public istream, public ostream{/*do something*/};\n```\n\n\nOk. \n\n\n## Exercise 18.22\n\n>Given the following class hierarchy, in which each class defines a default constructor.\n>What is the order of constructor execution for the following definition.\n\n```cpp\n#include <iostream>\n\nclass A {};\nclass B : public A{};\nclass C : public B{};\n\nclass X {};\nclass Y {};\nclass Z : public X, public Y {};\n\nclass MI : public C, public Z {};\nclass D : public X, public C{};\n\nMI mi;\n\nint main()\n{\n*pd = new D;\nX *px = pd;\nB *pb = pd;\nA *pa =pd;\nC *pc = pd;\nreturn 0;\n}\n```\n\n\nThe order in which base classes are constructed depends on the order in which they appear in the class derivation list.\nconstruction order is as follows: A, B, C, X, Y, Z, MI.  \n\n## Exercise 18.23\n\n>Using the hierarchy in exercise 18.22 along with class D defined below, and assuming each class defines a default constructor, which,if any,\nof the following conversion are not permitted?\n\n```cpp\nclass D : public c{ ... };\nD *pd = new D;\n\n```\nAll of the conversions are permitted.\n\n\n## Exercise 18.24\n\n>On page 807 we presented a series of calls made through a Bear pointer that pointed to a Panda object.\n>Explain each call assuming we used a ZooAnimal pointer pointing to a Panda Object instead.\n\n```cpp\nZooAnimal *pb = new Panda (\"ying_yang\");\n\npb->print();//Ok, part of ZooAnimal interface\npb->cuddle();//Error, not part of interface\npb->highlight();//Error, not part of interface\ndelete pb;//Ok, part of interface\n```\n\n## Exercise 18.25\n\n>Assume we have two base classes, Base1 and Base 2, each of which\n>define a virtual member named print and a virtual destructor.  From these base\n>classes we derive the following classes, each of which redefines the print function.\n\n[cpp](./ex18.25.cpp \"Exercise 18.25\")\n\n## Exercise 18.26\n\n>Given the hierarchy in the box on page 810, why is the following call to print an error?\n>Revise MI to allow this call to print to compile and execute correctly.\n\n```cpp\n#include <iostream>\n#include <vector>\nstruct Base1{\n    void print(int) const{\n        std::cout<<\"Base1 Print Used\"<<std::endl;\n        };\nprotected:\n        int ival;\n        double dval;\n        char cval;\nprivate:\n        int *id;\n};\nstruct Base2 {\n    void print(double) const;\nprotected:\n    double fval;\nprivate:\n    double dval;\n};\n\nstruct Derived : public Base1 {\nvoid print(std::string) const;\nprotected:\n    std::string sval;\n    double dval;\n};\n\nstruct MI : public Derived, public Base2{\n\nvoid print(std::vector<double>){};\nvoid print(int x){\n    Base1::print(x);\n}\nprotected:\n    int *ival;\n    std::vector<double> dvec;\n};\n\nusing namespace std;\n\nint main()\n{\n    MI mi;\n    mi.print(42);\n    return 0;\n}\n```\n\nThere is no matching version of print in MI that matches an integer argument.  If we just remove the print function in MI there is an ambiguity between the Derived and Base2 versions\nof print; therefore, we should overload the MI version of print() to take an int argument.\n\n## Exercise 18.27\n\n>Given the hierarchy in the box on page 810, why is the following call to print an error?\n>Revise MI to allow this call to print to compile and execute correctly.\n\n```cpp\n#include <iostream>\n#include <vector>\nstruct Base1{\n    void print(int) const{\n        std::cout<<\"Base1 Print Used\"<<std::endl;\n        };\nprotected:\n    int ival;\n    double dval;\n    char cval;\nprivate:\n    int *id;\n};\n\nstruct Base2 {\n    void print(double) const;\nprotected:\n    double fval;\nprivate:\n    double dval;\n};\n\nstruct Derived : public Base1 {\n    void print(std::string) const;\nprotected:\n    std::string sval=std::string(1,Base1::cval);//(e)\n    double dval;\n};\n\nstruct MI : public Derived, public Base2{\n\nvoid print(std::vector<double>){};\nvoid print(int x){\n    Base1::print(x);\n}\n\nint ival;\ndouble dval;\n\nvoid foo(double cval)\n    {\n        int dval;\n        dval = Base1::dval+Derived::dval;//(c)\n        Base2::fval=dvec.back()-1;//(d)\n        Derived::sval[0]= Base1::cval;//(e)\n        std::cout<<dval;\n    }\nprotected:\n    std::vector<double> dvec={9,8,7};\n};\n\nint main()\n{\n    MI mi;\n    return 0;\n}\n```\n\n(a) Everything that is a property of the classes that MI derives from is visible except those that are private.\n(b) Yes any names in the base classes that repeat and are not private can be accessed in foo by adding a scope operator.\n(c) see above\n(d) see above\n(e) see above\n\n## Exercise 18.28\n\n>Given the following class hierarchy, which inherited members can be accessed without qualification, from within the vmi class?\n>which require qualification? Explain your reasoning.\n\n```cpp\nstruct Base{\n    void bar(int); //Accessed without qualification, not defined with int arg anywhere\nprotected:\n    int ival;//Need qualification, VMI will use Derived2::ival by default\n};\n\nstruct Derived1 : virtual public Base{\n    void bar(char);//Accessed with no qualification, VMI derives from Derived1 which derives from Base.\n    void foo(char);//Need qualification, can convert arg between two foos.\nprotected:\n    char cval;//need to qualify ambiguous with other cval.\n};\n\nstruct Derived2 : virtual public Base{\nvoid foo(int);//Need qualification, can convert arg between two foos.\nprotected:\n    int ival;//Accessed with no qualification.\n    char cval;//need to qualify ambiguous with other cval.\n};\nclass VMI : public Derived1, public Derived2 { };\n```\n"
  },
  {
    "path": "ch18/ex18.1.2.3.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Alan.W\n *  @date       11  Mar 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 18.1:\n// What is the type of the exception object in the following throws?\n//     (a) range_error r(\"error\");\n//         throw r;\n//     (b) exception *p = &r;\n//         throw *p;\n//  the static, compile-time type of that expression determines the type of\n//  the exception object.\n//  so the object thrown the second time is std::exception type not std::range_error.\n// What would happen if the throw in (b) were written as throw p?\n//  terminate called after throwing an instance of 'std::exception*'\n//\n// Exercise 18.2: Explain what happens if an exception occurs at the indicated point:\n/*\nvoid exercise(int *b, int *e)\n{\n    vector<int> v(b, e);            // the object v will be destroyed by its destructor.\n    int *p = new int[v.size()];     // the dynamically allocated int array will be no way deallocated.\n    ifstream in(\"ints\");            // the object in will be destroyed.\n    // exception occurs here\n}\n*/\n// Exercise 18.3:\n// There are two ways to make the previous code work correctly\n// if an exception is thrown. Describe them and implement them.\n//  The first approach is to mange it using a class. The second one is using smart pointer.\n//\n\n#include <iostream>\n#include <stdexcept>\n#include <memory>\n#include <vector>\n#include <fstream>\n/**\n * @brief The intArray class manage a dynamicly allocated int array.\n * @note  for ex18.3 approach 1.\n */\nstruct intArray\n{\n    intArray() : p(nullptr) { }\n    explicit    intArray(std::size_t s):\n        p(new int[s])       { }\n\n\n    ~intArray()\n    {\n        delete[] p;\n    }\n\n    // data meber\n    int *p;\n};\n\nvoid exercise(int *b, int *e)\n{\n    std::vector<int> v(b, e);            // the object v will be destroyed by its destructor.\n\n    // @oldcode:\n    //int *p = new int[v.size()];     // the dynamically allocated int array will be no way deallocated.\n\n    // approach 1:\n    intArray p(v.size());\n\n    // approach 2:\n    //std::shared_ptr<int> p(new int[v.size()], [](int *p) { delete[] p; });\n                                                // delete array using lambda\n\n    std::ifstream in(\"ints\");            // the object in will be destroyed.\n    // exception occurs here\n}\n\nint main()\n{\n    // for ex18.1\n    /*\n    std::range_error r(\"error\");\n    //throw r;\n\n    std::exception *p = &r;\n    throw p;\n    */\n    return 0;\n}\n\n\n"
  },
  {
    "path": "ch18/ex18.12.13.14.cpp",
    "content": "/***************************************************************************\n *  @file       main.cpp\n *  @author     Queequeg\n *  @date       20  Nov 2014\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n //\n// Exercise 18.12\n// Organize the programs you have written to answer the questions in each\n// chapter into their own namespaces. That is, namespace chapter15 would\n// contain code for the Query programs and chapter10 would contain the\n// TextQuery code. Using this structure, compile the Query code examples.\n\n// Exercise 18.13\n// When might you see use an unnamed namespace?\n// http://stackoverflow.com/questions/154469/unnamed-anonymous-namespaces-vs-static-functions\n// http://stackoverflow.com/questions/5312213/uses-of-unnamed-namespace-in-c\n\n// Exercise 18.14\n// Suppose we have the following declaration of the operator* that is a\n// a member of the nested namespace mathLib::MatrixLib.\n// How would you declare this operator in global scope?\n\n// mathLib::MatrixLib::matrix mathLib::MatrixLib::operator*\n// (const mathLib::MatrixLib::matrix&, const mathLib::MatrixLib::matrix&);\n\n// or :(provided by @lafener in #173)\n\n//mathLib::MatrixLib::matrix mathLib::MatrixLib::operator* (const matrix&, const matrix&);\n\nint main()\n{\n    return 0;\n}\n"
  },
  {
    "path": "ch18/ex18.15.16.17.cpp",
    "content": "/***************************************************************************\r\n *  @file       main.cpp\r\n *  @author     Queequeg\r\n *  @date       20  Nov 2014\r\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\r\n *  @note\r\n ***************************************************************************/\r\n//\r\n// Exercise 18.15\r\n// Explain the differences between using declarations and directives.\r\n// This difference in scope between a using declaration and a using directive\r\n// stems directly from how these two facilities work. In the case of a using\r\n// declaration, we are simply making name directly accessible in the local\r\n// scope. In contrast, a using directive makes the entire contents of a\r\n// namespace available In general, a namespace might include definitions that\r\n// cannot appear in a local scope. As a consequence, a using directive is\r\n// treated as if it appeared in the nearest enclosing namespace scope.\r\n\r\n// Exercise 18.16\r\n// Explain the following code assuming using declarations for all the\r\n// members of namespace Exercise are located at the location labeled\r\n// position 1. What if they appear at position 2 instead? Now answer the\r\n// same question but replace the using declarations with a using directive\r\n// for namespace Exercise.\r\n\r\n// Exercise 18.17\r\n// Write code to test your answers to the previous question.\r\n\r\n\r\n#include <iostream>\r\nusing std::cout;\r\nusing std::endl;\r\n\r\n// using declarations for all the members of namespace Exercise\r\n// are located at the location labeled position 1.\r\nnamespace Test0\r\n{\r\n\tnamespace Exercise\r\n\t{\r\n\t\tint ivar = 0;\r\n\t\tdouble dvar = 0;\r\n\t\tconst int limit = 1000;\r\n\t}\r\n\r\n\tint ivar = 0;\r\n\r\n\t// using Exercise::ivar;\r\n\t// error C2874: using-declaration causes a multiple declaration of 'Test0::Exercise::ivar'\r\n\t// So we delete it to make the program compile.\r\n\tusing Exercise::dvar;\r\n\tusing Exercise::limit;\r\n\r\n\tvoid manip()\r\n\t{\r\n\t\tdouble dvar = 3.1416;\r\n\r\n\t\tcout << \"********** Before call Test0::manip **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test0::ivar \" << Test0::ivar << endl\r\n\t\t     << \"dvar in function manip\" << dvar << endl;\r\n\r\n\t\tint iobj = limit + 1;  // Exercise::limit + 1\r\n\t\t++ivar;                // ++ Test0::ivar\r\n\t\t++Test0::ivar;         // ++ Test0::ivar\r\n\r\n\t\tcout << \"********** After call Test0::manip  **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test0::ivar \" << Test0::ivar << endl\r\n\t\t     << \"dvar in function manip \" << dvar << endl\r\n\t\t\t << \"iboj in function manip \" << iobj << endl;\r\n\t}\r\n}\r\n\r\n\r\n// using declarations for all the members of namespace Exercise\r\n// are located at the location labeled position 2.\r\nnamespace Test1\r\n{\r\n\tnamespace Exercise\r\n\t{\r\n\t\tint ivar = 0;\r\n\t\tdouble dvar = 0;\r\n\t\tconst int limit = 1000;\r\n\t}\r\n\r\n\tint ivar = 0;\r\n\r\n\tvoid manip()\r\n\t{\r\n\t\tusing Exercise::ivar;\r\n\t    // using Exercise::dvar;\r\n\t\t// This using declaration causes a redefinition of Test1::Exercise::dvar.\r\n\t    // So we delete it to make the program compile.\r\n\t    using Exercise::limit;\r\n\r\n\t\tdouble dvar = 3.1416;\r\n\r\n\t\tcout << \"********** Before call Test1::manip **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test1::ivar \" << Test1::ivar << endl\r\n\t\t     << \"dvar in function manip\" << dvar << endl;\r\n\r\n\t\tint iobj = limit + 1; // Exercise::limit + 1\r\n\t\t++ivar;               // ++ Exercise::ivar\r\n\t\t++Test1::ivar;        // ++ Test1::ivar\r\n\r\n\t\tcout << \"********** After call Test1::manip  **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test1::ivar \" << Test1::ivar << endl\r\n\t\t     << \"dvar in function manip \" << dvar << endl\r\n\t\t\t << \"iboj in function manip \" << iobj << endl;\r\n\t}\r\n}\r\n\r\n// using directive for namespace Exercise is located at the\r\n// location labeled position 1.\r\nnamespace Test2\r\n{\r\n\tnamespace Exercise\r\n\t{\r\n\t\tint ivar = 0;\r\n\t\tdouble dvar = 0;\r\n\t\tconst int limit = 1000;\r\n\t}\r\n\r\n\tint ivar = 0;\r\n\r\n\tusing namespace Exercise;\r\n\r\n\tvoid manip()\r\n\t{\r\n\t\tdouble dvar = 3.1416;\r\n\r\n\t\tcout << \"********** Before call Test2::manip **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test2::ivar \" << Test2::ivar << endl\r\n\t\t     << \"dvar in function manip\" << dvar << endl;\r\n\r\n\t\tint iobj = limit + 1; // Exercise::limit + 1\r\n\t\t// ++ivar;\r\n\t\t// error C2872: 'ivar' : ambiguous symbol\r\n\t\t// could be int Test2::ivar or int Test2::Exercise::ivar\r\n\t\t++Test2::ivar;        // ++ Test2::ivar\r\n\r\n\t\tcout << \"********** After call Test2::manip  **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test2::ivar \" << Test2::ivar << endl\r\n\t\t     << \"dvar in function manip \" << dvar << endl\r\n\t\t\t << \"iboj in function manip \" << iobj << endl;\r\n\t}\r\n}\r\n\r\n// using directive for namespace Exercise is located at the\r\n// location labeled position 2.\r\n\r\nnamespace Test3\r\n{\r\n\tnamespace Exercise\r\n\t{\r\n\t\tint ivar = 0;\r\n\t\tdouble dvar = 0;\r\n\t\tconst int limit = 1000;\r\n\t}\r\n\r\n\tint ivar = 0;\r\n\r\n\tvoid manip()\r\n\t{\r\n\t\tusing namespace Exercise;\r\n\r\n\t\tdouble dvar = 3.1416;\r\n\r\n\t\tcout << \"********** Before call Test3::manip **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test3::ivar \" << Test3::ivar << endl\r\n\t\t     << \"dvar in function manip\" << dvar << endl;\r\n\r\n\t\tint iobj = limit + 1; // Exercise::limit + 1\r\n\t\t// ++ivar;\r\n\t\t// error C2872: 'ivar' : ambiguous symbol\r\n\t\t// could be int Test3::ivar or int Test3::Exercise::ivar\r\n\t\t++Test3::ivar;        // ++ Test3::ivar\r\n\r\n\t\tcout << \"********** After call Test3::manip  **********\" << endl;\r\n\t\tcout << \"Exercise::ivar \" << Exercise::ivar << endl\r\n\t\t\t << \"Exercise::dvar \" << Exercise::dvar << endl\r\n\t\t     << \"Exercise::limit \" << Exercise::limit <<endl\r\n\t\t     << \"Test3::ivar \" << Test3::ivar << endl\r\n\t\t     << \"dvar in function manip \" << dvar << endl\r\n\t\t\t << \"iboj in function manip \" << iobj << endl;\r\n\t}\r\n}\r\n\r\nint main()\r\n{\r\n\tTest0::manip();\r\n\tcout << endl;\r\n\r\n\tTest1::manip();\r\n\tcout << endl;\r\n\r\n\tTest2::manip();\r\n\tcout << endl;\r\n\r\n\tTest3::manip();\r\n\tcout << endl;\r\n\r\n\treturn 0;\r\n}\r\n\r\n"
  },
  {
    "path": "ch18/ex18.25.cpp",
    "content": "/***************************************************************************\n *  @file       ex18.25.cpp\n *  @author     eipi10\n *  @date       15  Aug 2016\n *  @remark     This code is for the exercises from C++ Primer 5th Edition\n *  @note\n ***************************************************************************/\n//\n// Exercise 18.25\n// Assume we have two base classes, Base1 and Base 2, each of which define a \n// virtual member named print and a virtual destructor. From these base classes \n// we derive the following classes, each of which redefines the print function.\n// Answer:\n// (a)MI\n// (b)MI\n// (c)MI\n// (d)MI, D2, Base2, D1, Base1\n// (e)MI, D2, Base2, D1, Base1\n// (f)MI, D2, Base2, D1, Base1\n// (d), (e), (f) will call all the destructor, for \"Destructors are always \n// invoked in the reverse order from which the constructors are run.\" in\n// Page 805\n\n// gcc 6.1.0 x86_64-pc-linux-gnu\n// results:\n// pb1 print...........\n// Print from MI\n// pd1 print...........\n// Print from MI\n// pd2 print...........\n// Print from MI\n// delete pb2...........\n// MI\n// D2\n// Base2\n// D1\n// Base1\n// delete pd1...........\n// MI\n// D2\n// Base2\n// D1\n// Base1\n// delete pd2...........\n// MI\n// D2\n// Base2\n// D1\n// Base1\n\n#include <iostream>\n\nstruct Base1\n{\n\t/* ... */\n\tvirtual void print(){std::cout << \"Print from Base1\" << std::endl;}\n\tvirtual ~Base1(){std::cout << \"Base1\" << std::endl;}\n};\nstruct Base2\n{\n\t/* ... */\n\tvirtual void print(){std::cout << \"Print from Base2\" << std::endl;}\n\tvirtual ~Base2(){std::cout << \"Base2\" << std::endl;}\n};\n\nstruct D1 : public Base1 \n{\n\t/* ... */\n\tvoid print() override {std::cout << \"Print from D1\" << std::endl;}\n\t~D1() override {std::cout << \"D1\" << std::endl;}\n};\nstruct D2 : public Base2 \n{\n\t/* ... */\n\tvoid print() override {std::cout << \"Print from D2\" << std::endl;}\n\t~D2() override {std::cout << \"D2\" <<std::endl;}\n};\nstruct MI : public D1, public D2 \n{\n\t/* ... */\n\tvoid print() override {std::cout << \"Print from MI\" << std::endl;}\n\t~MI() override {std::cout << \"MI\" << std::endl;}\n};\n\n//Using the following pointers, determine which funciton is used in each call:\n\nint main()\n{\n\tBase1 *pb1 = new MI;\n\tBase2 *pb2 = new MI;\n\tD1 *pd1 =new MI;\n\tD2 *pd2 = new MI;\n\tstd::cout << \"pb1 print...........\" << std::endl;\n\tpb1 -> print();\n\tstd::cout << \"pd1 print...........\" << std::endl;\n\tpd1 -> print();\n\tstd::cout << \"pd2 print...........\" << std::endl;\n\tpd2 -> print();\n\tstd::cout << \"delete pb2...........\" << std::endl;\n\tdelete pb2;\n\tstd::cout << \"delete pd1...........\" << std::endl;\n\tdelete pd1;\n\tstd::cout << \"delete pd2...........\" << std::endl;\n\tdelete pd2;\n}\n"
  },
  {
    "path": "ch18/ex18_29.cpp",
    "content": "/* Exercise 18.29: \n\nGiven the following class hierarchy: \n\nclass Class { ... }; class Base : public Class { ... }; \nclass D1 : virtual public Base { ... }; \nclass D2 : virtual public Base { ... }; \nclass MI : public D1, public D2 { ... }; \nclass Final : public MI, public Class { ... }; \n\n(a) In what order are constructors and destructors run on a Final object? \n(b) A Final object has how many Base parts? How many Class parts? \n(c) Which of the following assignments is a compile-time error? \n\nBase *pb;    Class *pc;       MI *pmi;     D2 *pd2; \n(a) pb = new Class; \t(b) pc = new Final; \n(c) pmi = pb; \t\t\t(d) pd2 = pmi;\n\nSolution: \n(a) Constructors run order: Class Base D1 D2 MI Class Final.\n\tDestructors run order: Final Class MI D2 D1 Base Class.\n\tClass parts are constructed from left to right and base class to derived class.\n(b) 1 Base part and 2 Class parts.\n\tBecause ‘Base’ is a virtual base class of ‘D1’ and ‘D2’. There is only 1 Base part. \n\tHowever, ‘Class’ is a normal base class of ‘Final’ and ‘Base’. So there is 2 Class part.\n(c) error. Can't convert a pointer of base class to a pointer of derived class implicitly.\n\terror. ‘Class’ is an ambiguous base of ‘Final’.\n\terror. Can't convert a pointer of base class to a pointer of derived class implicitly.\n\tpass. A pointer of derived class can be cast to a pointer of base class.\n\n*/\n#include <iostream>\n\nusing namespace std;\n\nclass Class {\npublic:\n\tClass() { cout << \"Class() called\" << endl; }\n\t~Class() { cout << \"~Class() called\" << endl; }\n};\n\nclass Base : public Class {\npublic:\n\tBase() { cout << \"Base() called\" << endl; }\n\t~Base() { cout << \"~Base() called\" << endl; }\n};\n\nclass D1 : virtual public Base {\npublic:\n\tD1() { cout << \"D1() called\" << endl; }\n\t~D1() { cout << \"~D1() called\" << endl; }\n};\n\nclass D2 : virtual public Base {\npublic:\n\tD2() { cout << \"D2() called\" << endl; }\n\t~D2() { cout << \"~D2() called\" << endl; }\n};\n\nclass MI : public D1, public D2 {\npublic:\n\tMI() { cout << \"MI() called\" << endl; }\n\t~MI() { cout << \"~MI() called\" << endl; }\n};\n\nclass Final : public MI, public Class {\npublic:\n\tFinal() { cout << \"Final() called\" << endl; }\n\t~Final() { cout << \"~Final() called\" << endl; }\n};\n\nint main(int argc, char const *argv[])\n{\n\tFinal final;\n\tBase *pb;\n\tClass *pc;\n\tMI *pmi;\n\tD2 *pd2;\n\t// pb = new Class;\n\t// pc = new Final;\n\t// pmi = pb;\n\tpd2 = pmi;\n\treturn 0;\n}\n"
  },
  {
    "path": "ch19/ex19_18.cpp",
    "content": "#include <iostream>\n#include <algorithm>\n#include <string>\n#include <functional>\n#include <vector>\n\nint main(int argc, char *argv[])\n{\n\tstd::vector< std::string > v;\n\tstd::string a;\n\twhile (std::getline(std::cin,a)) {\n\t\tv.push_back(a);\t\n\t}\n\tauto m = std::count_if(v.begin(),v.end(),std::mem_fn(&std::string::empty));\n\tstd::cout << \"Using mem_fn,the number of empty lines:\" << m << std::endl;\n\tauto n = std::count_if(v.begin(),v.end(),std::bind(&std::string::empty,std::placeholders::_1));\n\tstd::cout << \"Using bind,the number of empty lines:\" << n << std::endl;\n\tauto q = std::count_if(v.begin(),v.end(),[](std::string &tem){\n\t\t\treturn tem.empty();\n\t\t\t});\n\tstd::cout << \"Using lamba,the number of empty lines:\" << q << std::endl;\n\treturn 0;\n}\n"
  },
  {
    "path": "ch19/ex19_20.cpp",
    "content": "#include <iostream>\n#include <vector>\n#include <string>\n#include <fstream>\n#include <memory>\n#include <map>\n#include <set>\n#include <sstream>\nclass TextQuery {\n\tpublic:\n\t\tclass QueryResult;\n\t\tusing line_no = std::vector<std::string>::size_type;\n\t\tTextQuery(std::ifstream&);\n\t\tTextQuery::QueryResult query(const std::string&) const;\n\tprivate:\n\t\tstd::shared_ptr<std::vector<std::string> > file;\n\t\tstd::map<std::string, std::shared_ptr<std::set<line_no> > > wm;\t\n};\n\nclass TextQuery::QueryResult{\n\tfriend std::ostream& print(std::ostream&, const QueryResult&);\n\tpublic:\n\t\tQueryResult(std::string s, std::shared_ptr<std::set<line_no> > p,\n\t\t\t\tstd::shared_ptr<std::vector<std::string> > f):sought(s),lines(p),file(f){};\n\tprivate:\n\t\tstd::string sought; //query word\n\t\tstd::shared_ptr<std::set<line_no> > lines; //lines the word show\n\t\tstd::shared_ptr<std::vector<std::string> > file; //files show the word;\n};\n\nTextQuery::TextQuery(std::ifstream &is) : file(new std::vector<std::string> ){\n\tstd::string text;\n\twhile (getline(is, text)) {\n\t\tfile->push_back(text);\t\n\t\tint n = file->size() - 1;\n\t\tstd::istringstream line(text);\t\n\t\tstd::string word;\n\t\twhile (line >> word) {\n\t\t\tauto &lines = wm[word];\t\n\t\t\tif (!lines) {\n\t\t\t\tlines.reset(new std::set<line_no>);\t\n\t\t\t}\n\t\t\tlines->insert(n);\n\t\t}\n\t}\n}\n\nTextQuery::QueryResult\nTextQuery::query(const std::string &sought) const{\n\tstatic std::shared_ptr<std::set<line_no> > nodata(new std::set<line_no>);\n\tauto loc = wm.find(sought);\n\tif (loc == wm.end()) {\n\t\treturn TextQuery::QueryResult(sought, nodata, file);\t\t\n\t}\n\telse {\n\t\treturn TextQuery::QueryResult(sought,loc->second,file);\n\t}\n}\n\nstd::ostream &print (std::ostream & os, const TextQuery::QueryResult & qr)\n{\n\tos << qr.sought << \" occurls \" << qr.lines->size() << \" time(s)\" << std::endl; \n\tfor (auto i : *qr.lines) {\n\t\tos << \"\\t(line \" << i+1 << \") \" << *(qr.file->begin() + i) << std::endl;\t\n\t}\n\treturn os;\n}\n\nint main(int argc, char *argv[])\n{\n\tstd::ifstream file;\n\tfile.open(\"ex19_18.cpp\");\n\tTextQuery si(file);\n\tauto res = si.query(\"std\");\n\tprint(std::cout, res);\n\treturn 0;\n}\n"
  },
  {
    "path": "ch19/ex19_21_22_23_24_25.cpp",
    "content": "#include <iostream>\n#include <string>\nusing std::string;\nclass Sales_data{\npublic:\n    Sales_data() = default;\n    ~Sales_data() = default;\n    Sales_data(int i):a(i){}\n    Sales_data(const Sales_data &rhs):a(rhs.a){}\n    Sales_data& operator=(const Sales_data&rhs){\n        a = rhs.a;\n        return *this;\n    }\nprivate:\n    int a = 0;\n};\n\nclass Token{\npublic:\n    Token():tok(INT),ival(0){}\n    Token(const Token&t): tok(t.tok){copyUnion(t);}\n    ~Token(){\n        if(tok == STR) sval.~string();\n        if(tok == SAL) item.~Sales_data();\n    }\n    Token& operator=(Token &&);\n    Token(Token&&);\n    Token& operator=(const Token&);\n    Token& operator=(const string&);\n    Token& operator=(const int&);\n    Token& operator=(const char&);\n    Token& operator=(const Sales_data&);\nprivate:\n    enum { INT, CHAR, STR, SAL} tok;\n    union{\n        char cval;\n        int ival;\n        std::string sval;\n        Sales_data item;\n    };\n    void copyUnion(const Token&);\n    //move edition\n    void copyUnion(Token&&);\n};\nvoid Token::copyUnion(Token&& t){\n    switch (t.tok) {\n        case INT  : ival = t.ival; break;\n        case CHAR : cval = t.cval; break;\n        case STR  : std::move(t.sval);break;\n        case SAL  : std::move(t.item); break;\n    }\n}\nvoid Token::copyUnion(const Token &t){\n    switch (t.tok) {\n        case INT  : ival = t.ival; break;\n        case CHAR : cval = t.cval; break;\n        case STR  : new(&sval) string(t.sval);break;\n        case SAL  : new(&item) Sales_data(t.item); break;\n    }\n}\n\nToken& Token::operator=(const Token&t){\n    if(tok == STR && t.tok != STR) sval.~string();\n    if(tok == SAL && t.tok != SAL) item.~Sales_data();\n    if(tok == STR && t.tok == STR) sval = t.sval;\n    if(tok == SAL && t.tok == SAL) item = t.item;\n    else copyUnion(t);\n    tok = t.tok;\n    return *this;\n}\n\n//move constructor\nToken& Token::operator=(Token&& t){\n    if(this != &t){\n        this->~Token();\n        copyUnion(t);\n        tok = std::move(t.tok);\n    }\n    return *this;\n}\nToken::Token(Token &&t){\n    copyUnion(t);\n    tok = std::move(t.tok);\n}\n\n\n\nToken& Token::operator=(const Sales_data& rhs){\n    if(tok == STR) sval.~string();\n    if(tok == SAL)\n        item = rhs;\n    else\n        new(&item) Sales_data(rhs);\n    tok = SAL;\n    return *this;\n}\nToken& Token::operator=(const int& i){\n    if(tok == STR) sval.~string();\n    if(tok == SAL) item.~Sales_data();\n    ival = i;\n    tok = INT;\n    return *this;\n}\n\n\nint main(int argc, char const *argv[]) {\n    Token s;\n    Sales_data sal(5);\n    s =  sal;\n    int i = 5;\n    std::cout << i << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "ch19/ex19_3_4.cpp",
    "content": "/* Exercises Section 19.2.1 \n\nExercise 19.3: \n\nGiven the following class hierarchy in which each class defines a public default constructor and virtual destructor: \n\nclass A { . . . }; \nclass B : public A { . . . }; \nclass C : public B {  . . . }; \nclass D : public B, public A { . . . };\n\nwhich, if any, of the following dynamic_casts fail? \n(a) A *pa = new C;    \n\tB *pb = dynamic_cast< B* >(pa); \n(b) B *pb = new B;    \n\tC *pc = dynamic_cast< C* >(pb); \n(c) A *pa = new D;    \n\tB *pb = dynamic_cast< B* >(pa); \n\nSolution:\n(a) Succeed. The type of ‘pa’ (class type 'C') is publicly derived from the target type 'B'.\n(b) Fail. The type of ‘pb’ (class type 'B') is a public base class of the target type 'C'. ‘pc’ will equal to nullptr.\n(c) Fail. ‘A’ is an ambiguous base of ‘D’. Converting a pointer of 'D' to a pointer of 'A' is not allowed.\n\nExercise 19.4: \n\nUsing the classes defined in the first exercise, rewrite the following code to convert the expression *pa to the type C&: \n\nif (C *pc = dynamic_cast< C* >(pa))    \n\t// use C's members \n} else {    \n\t// use A's members \n} \n\nSolution:\n\ntry {\n\tC &rc = dynamic_cast<C&>(ra);\n\t// use C's members \n} catch (bad_cast) {\n\t// use A's members \n}\n\n*/\n\n#include <iostream>\n#include <typeinfo>\n\nusing namespace std;\n\nclass A {\npublic:\n\tvirtual ~A() {}\n};\n\nclass B : public A {\npublic:\n\tvirtual ~B() {}\n};\n\nclass C : public B {\npublic:\n\tvirtual ~C() {}\n};\n\nclass D : public B, public A {\npublic:\n\tvirtual ~D() {}\n};\n\nint main(int argc, char const *argv[])\n{\n\t/* Exercise 19.3 */\n\n\tA *pa = new C;    \n\tB *pb = dynamic_cast< B* >(pa); \n\tif (pb) cout << \"19.3 (a) succeed!\" << endl;\n\telse cout << \"19.3 (a) fail!\" << endl;\n\n\tpb = new B;    \n\tC *pc = dynamic_cast< C* >(pb); \n\tif (pc) cout << \"19.3 (b) succeed!\" << endl;\n\telse cout << \"19.3 (b) fail!\" << endl;\n\n/*\tpa = new D;    \n\tpb = dynamic_cast< B* >(pa); */\n\n\t/* Exercise 19.4 */\n\n\tC c; B b;\n\tA &ra1 = c, &ra2 = b;\n\ttry {\n\t\t/* succeed */\n\t\tC &rc1 = dynamic_cast<C&>(ra1);\n\t\tcout << \"19.4 succeed!\" << endl;\n\t\t/* fail */\n\t\tC &rc2 = dynamic_cast<C&>(ra2);\n\t} catch (bad_cast) {\n\t\tcout << \"19.4 failed!\" << endl;\n\t}\n\treturn 0;\n}"
  },
  {
    "path": "data/book.txt",
    "content": "0-201-78345-X 3 20\n0-201-78345-X 2 25\n0-201-78346-X 1 100\n0-201-78346-X 2 99.9\n0-201-78346-X 6 89.9\n"
  },
  {
    "path": "data/even.txt",
    "content": "2\n4\n6\n8\n"
  },
  {
    "path": "data/given_to_transform.txt",
    "content": "where r u \ny dont u send me a pic \nk thk l8r "
  },
  {
    "path": "data/input.txt",
    "content": "1 2 3 4 5 6 7 8 9\n"
  },
  {
    "path": "data/letter.txt",
    "content": "In typography, an ascender is the portion of a minuscule letter in a Latin-derived alphabet that extends above the mean line of a font. That is, the part of a lower-case letter that is taller than the font's x-height.\n\nAscenders, together with descenders, increase the recognizability of words. For this reason, British road signs no longer use all capital letters.[1]\n\nStudies made at the start of the construction of the British motorway network concluded that words with mixed-case letters were much easier to read than \"all-caps\" and a special font was designed for motorway signs. These then became universal across the U.K. See Road signs in the United Kingdom."
  },
  {
    "path": "data/odd.txt",
    "content": "1 3 5 7 9 "
  },
  {
    "path": "data/phonenumbers.txt",
    "content": "morgan 2015552368 8625550123\ndrew   9735550130\nlee    6095550132 2015550175 8005550000"
  },
  {
    "path": "data/storyDataFile.txt",
    "content": "Alice Emma has long flowing red hair. \nHer Daddy says when the wind blows \nthrough her hair, it looks almost alive, \nlike a fiery bird in flight. \nA beautiful fiery bird, he tells her, \nmagical but untamed. \n\"Daddy, shush, there is no such thing,\" \nshe tells him, at the same time wanting \nhim to tell her more.\nShyly, she asks, \"I mean, Daddy, is there?\"\n"
  },
  {
    "path": "data/word_transformation.txt",
    "content": "brb be right back \nk okay? \ny why \nr are \nu you \npic picture \nthk thanks! \nl8r later"
  },
  {
    "path": "data/word_transformation_bad.txt",
    "content": "l8r "
  },
  {
    "path": "include/Sales_item.h",
    "content": "/*\n * This file contains code from \"C++ Primer, Fifth Edition\", by Stanley B.\n * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the\n * \n * \n * \n * \"The authors and publisher have taken care in the preparation of this book,\n * but make no expressed or implied warranty of any kind and assume no\n * responsibility for errors or omissions. No liability is assumed for\n * incidental or consequential damages in connection with or arising out of the\n * use of the information or programs contained herein.\"\n * \n * Permission is granted for this code to be used for educational purposes in\n * association with the book, given proper citation if and when posted or\n * reproduced.Any commercial use of this code requires the explicit written\n * permission of the publisher, Addison-Wesley Professional, a division of\n * Pearson Education, Inc. Send your request for permission, stating clearly\n * what code you would like to use, and in what specific way, to the following\n * address: \n * \n *     Pearson Education, Inc.\n *     Rights and Permissions Department\n *     One Lake Street\n *     Upper Saddle River, NJ  07458\n *     Fax: (201) 236-3290\n*/ \n\n/* This file defines the Sales_item class used in chapter 1.\n * The code used in this file will be explained in\n * Chapter 7 (Classes) and Chapter 14 (Overloaded Operators)\n * Readers shouldn't try to understand the code in this file\n * until they have read those chapters.\n*/\n\n#ifndef SALESITEM_H\n// we're here only if SALESITEM_H has not yet been defined \n#define SALESITEM_H\n\n// Definition of Sales_item class and related functions goes here\n#include <iostream>\n#include <string>\n\nclass Sales_item {\n// these declarations are explained section 7.2.1, p. 270 \n// and in chapter 14, pages 557, 558, 561\nfriend std::istream& operator>>(std::istream&, Sales_item&);\nfriend std::ostream& operator<<(std::ostream&, const Sales_item&);\nfriend bool operator<(const Sales_item&, const Sales_item&);\nfriend bool \noperator==(const Sales_item&, const Sales_item&);\npublic:\n    // constructors are explained in section 7.1.4, pages 262 - 265\n    // default constructor needed to initialize members of built-in type\n    Sales_item() = default;\n    Sales_item(const std::string &book): bookNo(book) { }\n    Sales_item(std::istream &is) { is >> *this; }\npublic:\n    // operations on Sales_item objects\n    // member binary operator: left-hand operand bound to implicit this pointer\n    Sales_item& operator+=(const Sales_item&);\n    \n    // operations on Sales_item objects\n    std::string isbn() const { return bookNo; }\n    double avg_price() const;\n// private members as before\nprivate:\n    std::string bookNo;      // implicitly initialized to the empty string\n    unsigned units_sold = 0; // explicitly initialized\n    double revenue = 0.0;\n};\n\n// used in chapter 10\ninline\nbool compareIsbn(const Sales_item &lhs, const Sales_item &rhs) \n{ return lhs.isbn() == rhs.isbn(); }\n\n// nonmember binary operator: must declare a parameter for each operand\nSales_item operator+(const Sales_item&, const Sales_item&);\n\ninline bool \noperator==(const Sales_item &lhs, const Sales_item &rhs)\n{\n    // must be made a friend of Sales_item\n    return lhs.units_sold == rhs.units_sold &&\n           lhs.revenue == rhs.revenue &&\n           lhs.isbn() == rhs.isbn();\n}\n\ninline bool \noperator!=(const Sales_item &lhs, const Sales_item &rhs)\n{\n    return !(lhs == rhs); // != defined in terms of operator==\n}\n\n// assumes that both objects refer to the same ISBN\nSales_item& Sales_item::operator+=(const Sales_item& rhs) \n{\n    units_sold += rhs.units_sold; \n    revenue += rhs.revenue; \n    return *this;\n}\n\n// assumes that both objects refer to the same ISBN\nSales_item \noperator+(const Sales_item& lhs, const Sales_item& rhs) \n{\n    Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return\n    ret += rhs;           // add in the contents of (|rhs|) \n    return ret;           // return (|ret|) by value\n}\n\nstd::istream& \noperator>>(std::istream& in, Sales_item& s)\n{\n    double price;\n    in >> s.bookNo >> s.units_sold >> price;\n    // check that the inputs succeeded\n    if (in)\n        s.revenue = s.units_sold * price;\n    else \n        s = Sales_item();  // input failed: reset object to default state\n    return in;\n}\n\nstd::ostream& \noperator<<(std::ostream& out, const Sales_item& s)\n{\n    out << s.isbn() << \" \" << s.units_sold << \" \"\n        << s.revenue << \" \" << s.avg_price();\n    return out;\n}\n\ndouble Sales_item::avg_price() const\n{\n    if (units_sold) \n        return revenue/units_sold; \n    else \n        return 0;\n}\n#endif\n"
  }
]