├── .gitmodules ├── BeginningCpp23.jpg ├── CMakeLists.txt ├── Compiling.md ├── Contributing.md ├── Errata.md ├── Examples ├── Appendix A │ ├── ExA_01 │ │ └── ExA_01.cpp │ ├── ExA_02 │ │ └── ExA_02.cpp │ ├── ExA_02A │ │ └── ExA_02A.cpp │ ├── ExA_03 │ │ └── ExA_03.cpp │ ├── ExA_04 │ │ ├── ExA_04.cpp │ │ └── inclusivity.quote │ ├── ExA_05 │ │ └── ExA_05.cpp │ ├── ExA_06 │ │ └── ExA_06.cpp │ ├── ExA_07 │ │ ├── ExA_07.cpp │ │ └── Power.cpp │ ├── ExA_07A │ │ ├── ExA_07A.cpp │ │ ├── Power.cpp │ │ └── Power.h │ ├── ExA_08 │ │ ├── ExA_08.cpp │ │ ├── Power.cpp │ │ └── Range.cpp │ ├── ExA_08A │ │ ├── ExA_08A.cpp │ │ ├── Power.cpp │ │ └── Range.cpp │ ├── ExA_09 │ │ ├── ExA_09.cpp │ │ └── Power.cpp │ ├── ExA_09A │ │ ├── ExA_09A.cpp │ │ └── Power.cpp │ ├── ExA_10 │ │ ├── BadMath.h │ │ └── ExA_10.cpp │ ├── ExA_10A │ │ ├── BetterMath.h │ │ └── ExA_10A.cpp │ ├── ExA_11 │ │ ├── BetterMath.h │ │ ├── ExA_11.cpp │ │ ├── Hypot.cpp │ │ ├── Hypot.h │ │ ├── Pow4.cpp │ │ └── Pow4.h │ ├── ExA_12 │ │ ├── ExA_12.cpp │ │ ├── Hypot.cpp │ │ ├── Hypot.h │ │ ├── Pow4.cpp │ │ ├── Pow4.h │ │ └── ProperMath.h │ ├── ExA_13 │ │ ├── Box.cpp │ │ ├── Box.h │ │ └── ExA_13.cpp │ └── ExA_13A │ │ ├── Box.h │ │ └── ExA_13A.cpp ├── Chapter 01 │ └── Ex1_01.cpp ├── Chapter 02 │ ├── Ex2_01.cpp │ ├── Ex2_02.cpp │ ├── Ex2_03.cpp │ ├── Ex2_04.cpp │ ├── Ex2_04A.cpp │ ├── Ex2_04B.cpp │ ├── Ex2_04C.cpp │ ├── Ex2_04D.cpp │ ├── Ex2_04E.cpp │ ├── Ex2_05.cpp │ ├── Ex2_06.cpp │ ├── Ex2_07.cpp │ ├── Ex2_08.cpp │ └── Ex2_08A.cpp ├── Chapter 03 │ ├── Ex3_01.cpp │ ├── Ex3_02.cpp │ └── Ex3_03.cpp ├── Chapter 04 │ ├── Ex4_01.cpp │ ├── Ex4_02.cpp │ ├── Ex4_02A.cpp │ ├── Ex4_03.cpp │ ├── Ex4_04.cpp │ ├── Ex4_04A.cpp │ ├── Ex4_05.cpp │ ├── Ex4_06.cpp │ ├── Ex4_07.cpp │ ├── Ex4_08.cpp │ ├── Ex4_09.cpp │ ├── Ex4_09A.cpp │ └── Ex4_10.cpp ├── Chapter 05 │ ├── Ex5_01.cpp │ ├── Ex5_02.cpp │ ├── Ex5_03.cpp │ ├── Ex5_03A.cpp │ ├── Ex5_03B.cpp │ ├── Ex5_04.cpp │ ├── Ex5_04A.cpp │ ├── Ex5_05.cpp │ ├── Ex5_06.cpp │ ├── Ex5_07.cpp │ ├── Ex5_07A.cpp │ ├── Ex5_08.cpp │ ├── Ex5_09.cpp │ ├── Ex5_10.cpp │ ├── Ex5_11.cpp │ ├── Ex5_12.cpp │ ├── Ex5_12A.cpp │ ├── Ex5_13.cpp │ ├── Ex5_14.cpp │ ├── Ex5_15.cpp │ └── Ex5_16.cpp ├── Chapter 06 │ ├── Ex6_01.cpp │ ├── Ex6_02.cpp │ ├── Ex6_03.cpp │ ├── Ex6_04.cpp │ ├── Ex6_05.cpp │ ├── Ex6_06.cpp │ └── Ex6_07.cpp ├── Chapter 07 │ ├── Ex7_01.cpp │ ├── Ex7_01A.cpp │ ├── Ex7_02.cpp │ ├── Ex7_02A.cpp │ ├── Ex7_03.cpp │ ├── Ex7_04.cpp │ ├── Ex7_05.cpp │ ├── Ex7_06.cpp │ └── Ex7_07.cpp ├── Chapter 08 │ ├── Ex8_01.cpp │ ├── Ex8_02.cpp │ ├── Ex8_03.cpp │ ├── Ex8_04.cpp │ ├── Ex8_05.cpp │ ├── Ex8_05A.cpp │ ├── Ex8_06.cpp │ ├── Ex8_06A.cpp │ ├── Ex8_07.cpp │ ├── Ex8_08.cpp │ ├── Ex8_09A.cpp │ ├── Ex8_09B.cpp │ ├── Ex8_09C.cpp │ ├── Ex8_10.cpp │ ├── Ex8_11.cpp │ ├── Ex8_12.cpp │ ├── Ex8_13.cpp │ ├── Ex8_14.cpp │ ├── Ex8_15.cpp │ ├── Ex8_16.cpp │ ├── Ex8_17.cpp │ ├── Ex8_18.cpp │ ├── Ex8_19A.cpp │ ├── Ex8_19B.cpp │ └── Ex8_19C.cpp ├── Chapter 09 │ ├── Ex9_01.cpp │ ├── Ex9_02.cpp │ ├── Ex9_03.cpp │ ├── Ex9_04.cpp │ └── Ex9_04A.cpp ├── Chapter 10 │ ├── Ex10_01.cpp │ ├── Ex10_02.cpp │ ├── Ex10_03.cpp │ ├── Ex10_03A.cpp │ ├── Ex10_04.cpp │ └── Ex10_05.cpp ├── Chapter 11 │ ├── Ex11_01 │ │ ├── Ex11_01.cpp │ │ └── math.cppm │ ├── Ex11_01A │ │ ├── Ex11_01A.cpp │ │ └── math.cppm │ ├── Ex11_01B │ │ ├── Ex11_01B.cpp │ │ └── math.cppm │ ├── Ex11_02 │ │ ├── Ex11_02.cpp │ │ ├── from_roman.cpp │ │ ├── roman.cppm │ │ └── to_roman.cpp │ ├── Ex11_03 │ │ ├── Ex11_03.cpp │ │ ├── from_roman.cpp │ │ ├── roman.cppm │ │ └── to_roman.cpp │ ├── Ex11_04A │ │ ├── Ex11_04A.cpp │ │ ├── from_roman.cpp │ │ ├── from_roman.cppm │ │ ├── roman.cppm │ │ ├── to_roman.cpp │ │ └── to_roman.cppm │ ├── Ex11_04B │ │ ├── Ex11_04B.cpp │ │ ├── from_roman.cpp │ │ ├── roman-internals.cpp │ │ ├── roman.cppm │ │ └── to_roman.cpp │ ├── Ex11_05 │ │ ├── Ex11_05.cpp │ │ ├── from_roman.cpp │ │ ├── roman-from.cppm │ │ ├── roman-internals.cpp │ │ ├── roman-to.cppm │ │ └── roman.cppm │ ├── Ex11_06 │ │ └── Ex11_06.cpp │ ├── Ex11_06A │ │ ├── Ex11_06A.cpp │ │ └── squaring.cppm │ ├── Ex11_06B │ │ ├── Ex11_06B.cpp │ │ └── squaring.cppm │ ├── Ex11_07 │ │ ├── Ex11_07.cpp │ │ ├── math.cpp │ │ └── math.cppm │ └── Ex11_08 │ │ ├── Ex11_08.cpp │ │ └── squaring.cppm ├── Chapter 12 │ ├── Ex12_01 │ │ └── Ex12_01.cpp │ ├── Ex12_01A │ │ └── Ex12_01A.cpp │ ├── Ex12_02 │ │ └── Ex12_02.cpp │ ├── Ex12_03 │ │ └── Ex12_03.cpp │ ├── Ex12_04 │ │ └── Ex12_04.cpp │ ├── Ex12_05 │ │ └── Ex12_05.cpp │ ├── Ex12_06 │ │ └── Ex12_06.cpp │ ├── Ex12_07 │ │ ├── Box.cppm │ │ └── Ex12_07.cpp │ ├── Ex12_07A │ │ ├── Box.cppm │ │ └── Ex12_07A.cpp │ ├── Ex12_07B │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_07B.cpp │ ├── Ex12_08 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_08.cpp │ ├── Ex12_09 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_09.cpp │ ├── Ex12_10 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_10.cpp │ ├── Ex12_11 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_11.cpp │ ├── Ex12_12 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_12.cpp │ ├── Ex12_13 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_13.cpp │ ├── Ex12_14 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_14.cpp │ ├── Ex12_15 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_15.cpp │ ├── Ex12_16 │ │ ├── CylindricalBox.cpp │ │ ├── CylindricalBox.cppm │ │ └── Ex12_16.cpp │ ├── Ex12_17 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex12_17.cpp │ ├── Ex12_18 │ │ ├── Box.cppm │ │ ├── Ex12_18.cpp │ │ ├── Package.cpp │ │ ├── RandomBoxes.cppm │ │ ├── SharedBox.cppm │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ └── Ex12_19 │ │ ├── Box.cppm │ │ ├── Ex12_19.cpp │ │ ├── RandomBoxes.cppm │ │ ├── Truckload.cpp │ │ └── Truckload.cppm ├── Chapter 13 │ ├── Ex13_01 │ │ ├── Box.cppm │ │ └── Ex13_01.cpp │ ├── Ex13_02 │ │ ├── Box.cppm │ │ └── Ex13_02.cpp │ ├── Ex13_03 │ │ ├── Box.cppm │ │ └── Ex13_03.cpp │ ├── Ex13_03A │ │ ├── Box.cppm │ │ └── Ex13_03A.cpp │ ├── Ex13_04 │ │ ├── Box.cppm │ │ └── Ex13_04.cpp │ ├── Ex13_05 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex13_05.cpp │ ├── Ex13_06 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Ex13_06.cpp │ ├── Ex13_07 │ │ ├── Ex13_07.cpp │ │ └── Integer.cppm │ ├── Ex13_08 │ │ ├── Box.cppm │ │ └── Ex13_08.cpp │ ├── Ex13_09 │ │ ├── Box.cppm │ │ └── Ex13_09.cpp │ ├── Ex13_10 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ ├── Ex13_10.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ ├── Ex13_11 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ ├── Ex13_11.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ ├── Ex13_12 │ │ ├── Ex13_12.cpp │ │ ├── Message.cpp │ │ └── Message.cppm │ ├── Ex13_12A │ │ ├── Ex13_12A.cpp │ │ ├── Message.cpp │ │ └── Message.cppm │ └── Ex13_12B │ │ ├── Ex13_12B.cpp │ │ ├── Message.cpp │ │ └── Message.cppm ├── Chapter 14 │ ├── Ex14_01 │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_01.cpp │ ├── Ex14_01A │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_01A.cpp │ ├── Ex14_02 │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_02.cpp │ ├── Ex14_03 │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_03.cpp │ ├── Ex14_04 │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_04.cpp │ ├── Ex14_04A │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_04A.cpp │ ├── Ex14_04B │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_04B.cpp │ ├── Ex14_04C │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_04C.cpp │ ├── Ex14_05 │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_05.cpp │ ├── Ex14_06 │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ └── Ex14_06.cpp │ ├── Ex14_07 │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ ├── CerealPack.cppm │ │ ├── Ex14_07.cpp │ │ └── FoodContainer.cppm │ ├── Ex14_07A │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ ├── CerealPack.cppm │ │ ├── Ex14_07A.cpp │ │ └── FoodContainer.cppm │ └── Ex14_07B │ │ ├── Box.cppm │ │ ├── Carton.cppm │ │ ├── CerealPack.cppm │ │ ├── Ex14_07B.cpp │ │ └── FoodContainer.cppm ├── Chapter 15 │ ├── Ex15_01 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Ex15_01.cpp │ │ └── ToughPack.cppm │ ├── Ex15_02 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_02.cpp │ │ └── ToughPack.cppm │ ├── Ex15_03 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_03.cpp │ │ └── ToughPack.cppm │ ├── Ex15_04 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_04.cpp │ │ └── ToughPack.cppm │ ├── Ex15_05 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_05.cpp │ │ └── ToughPack.cppm │ ├── Ex15_06 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_06.cpp │ │ └── ToughPack.cppm │ ├── Ex15_07 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_07.cpp │ │ └── ToughPack.cppm │ ├── Ex15_08 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_08.cpp │ │ └── ToughPack.cppm │ ├── Ex15_09 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Ex15_09.cpp │ │ └── ToughPack.cppm │ ├── Ex15_10 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ └── Ex15_10.cpp │ ├── Ex15_11 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_11.cpp │ │ └── ToughPack.cppm │ └── Ex15_12 │ │ ├── Box.cppm │ │ ├── Boxes.cppm │ │ ├── Can.cppm │ │ ├── Carton.cppm │ │ ├── Ex15_12.cpp │ │ ├── ToughPack.cppm │ │ └── Vessel.cppm ├── Chapter 16 │ ├── Ex16_01 │ │ └── Ex16_01.cpp │ ├── Ex16_02 │ │ ├── Ex16_02.cpp │ │ └── Troubles.cppm │ ├── Ex16_03 │ │ ├── Ex16_03.cpp │ │ └── Troubles.cppm │ ├── Ex16_04 │ │ ├── Ex16_04.cpp │ │ └── Troubles.cppm │ ├── Ex16_05 │ │ ├── Ex16_05.cpp │ │ └── Troubles.cppm │ ├── Ex16_06 │ │ ├── Ex16_06.cpp │ │ └── Troubles.cppm │ ├── Ex16_07 │ │ ├── Ex16_07.cpp │ │ └── Troubles.cppm │ ├── Ex16_07A │ │ ├── Ex16_07A.cpp │ │ └── Troubles.cppm │ ├── Ex16_07B │ │ ├── DoubleArrayRAII.cppm │ │ ├── Ex16_07B.cpp │ │ └── Troubles.cppm │ ├── Ex16_07C │ │ ├── Ex16_07C.cpp │ │ └── Troubles.cppm │ ├── Ex16_07D │ │ ├── Ex16_07D.cpp │ │ └── Troubles.cppm │ ├── Ex16_08 │ │ ├── Box.cppm │ │ ├── DimensionError.cppm │ │ └── Ex16_08.cpp │ └── Ex16_09 │ │ ├── Ex16_09.cpp │ │ └── Tracing.cppm ├── Chapter 17 │ ├── Ex17_01 │ │ ├── Array.cppm │ │ ├── Box.cppm │ │ └── Ex17_01.cpp │ ├── Ex17_01A │ │ ├── Array.cppm │ │ ├── Box.cppm │ │ └── Ex17_01A.cpp │ ├── Ex17_02 │ │ ├── Array.cppm │ │ ├── Box.cppm │ │ └── Ex17_02.cpp │ ├── Ex17_02A │ │ ├── Array.cppm │ │ ├── Box.cppm │ │ └── Ex17_02A.cpp │ ├── Ex17_03 │ │ ├── Array.cppm │ │ ├── Box.cppm │ │ └── Ex17_03.cpp │ ├── Ex17_04 │ │ ├── Ex17_04.cpp │ │ └── Stack.cppm │ ├── Ex17_04A │ │ ├── Ex17_04A.cpp │ │ └── Stack.cppm │ ├── Ex17_04B │ │ ├── Ex17_04B.cpp │ │ └── Stack.cppm │ ├── Ex17_05 │ │ ├── Ex17_05A.cpp │ │ └── Ex17_05B.cpp │ └── Ex17_06 │ │ └── Ex17_06.cpp ├── Chapter 18 │ ├── Ex18_01 │ │ ├── Array.cppm │ │ └── Ex18_01.cpp │ ├── Ex18_02 │ │ ├── Array.cppm │ │ └── Ex18_02.cpp │ ├── Ex18_03 │ │ ├── Array.cppm │ │ └── Ex18_03.cpp │ ├── Ex18_04 │ │ ├── Array.cppm │ │ └── Ex18_04.cpp │ ├── Ex18_05A │ │ ├── Array.cppm │ │ └── Ex18_05A.cpp │ ├── Ex18_05B │ │ ├── Array.cppm │ │ └── Ex18_05B.cpp │ ├── Ex18_06 │ │ ├── Array.cppm │ │ └── Ex18_06.cpp │ └── Ex18_07 │ │ ├── Array.cppm │ │ └── Ex18_07.cpp ├── Chapter 19 │ ├── Ex19_01 │ │ └── Ex19_01.cpp │ ├── Ex19_02 │ │ ├── Ex19_02.cpp │ │ └── Optimum.cppm │ ├── Ex19_03 │ │ ├── Ex19_03.cpp │ │ ├── Less.cppm │ │ └── Optimum.cppm │ ├── Ex19_03A │ │ ├── Ex19_03A.cpp │ │ └── Optimum.cppm │ ├── Ex19_04 │ │ ├── Ex19_04.cpp │ │ ├── Nearer.cppm │ │ └── Optimum.cppm │ ├── Ex19_05 │ │ ├── Ex19_05.cpp │ │ └── Optimum.cppm │ ├── Ex19_05A │ │ ├── Ex19_05A.cpp │ │ └── Optimum.cppm │ ├── Ex19_05B │ │ ├── Ex19_05B.cpp │ │ └── Optimum.cppm │ ├── Ex19_06 │ │ ├── Ex19_06.cpp │ │ └── Optimum.cppm │ ├── Ex19_07 │ │ ├── Ex19_07.cpp │ │ ├── Finder.cpp │ │ ├── Finder.cppm │ │ └── Optimum.cppm │ └── Ex19_08 │ │ └── Ex19_08.cpp ├── Chapter 20 │ ├── Ex20_01 │ │ └── Ex20_01.cpp │ ├── Ex20_02 │ │ └── Ex20_02.cpp │ ├── Ex20_03 │ │ └── Ex20_03.cpp │ ├── Ex20_04 │ │ └── Ex20_04.cpp │ ├── Ex20_05 │ │ └── Ex20_05.cpp │ ├── Ex20_06 │ │ └── Ex20_06.cpp │ ├── Ex20_07 │ │ └── Ex20_07.cpp │ ├── Ex20_08 │ │ ├── Box.cppm │ │ └── Ex20_08.cpp │ ├── Ex20_09 │ │ └── Ex20_09.cpp │ ├── Ex20_10 │ │ └── Ex20_10.cpp │ ├── Ex20_11 │ │ └── Ex20_11.cpp │ ├── Ex20_11A │ │ └── Ex20_11A.cpp │ ├── Ex20_12 │ │ ├── Box.cppm │ │ └── Ex20_12.cpp │ ├── Ex20_12A │ │ ├── Box.cppm │ │ └── Ex20_12A.cpp │ ├── Ex20_13 │ │ └── Ex20_13.cpp │ ├── Ex20_13A │ │ └── Ex20_13A.cpp │ ├── Ex20_13B │ │ └── Ex20_13B.cpp │ ├── Ex20_14 │ │ └── Ex20_14.cpp │ ├── Ex20_14A │ │ └── Ex20_14A.cpp │ ├── Ex20_14B │ │ └── Ex20_14B.cpp │ ├── Ex20_15 │ │ └── Ex20_15.cpp │ ├── Ex20_15A │ │ └── Ex20_15A.cpp │ ├── Ex20_16 │ │ ├── Box.cppm │ │ └── Ex20_16.cpp │ ├── Ex20_17 │ │ └── Ex20_17.cpp │ ├── Ex20_18 │ │ └── Ex20_18.cpp │ └── Ex20_19 │ │ └── Ex20_19.cpp ├── Chapter 21 │ ├── Ex21_01 │ │ └── Ex21_01.cpp │ ├── Ex21_02 │ │ └── Ex21_02.cpp │ ├── Ex21_03 │ │ ├── Array.cppm │ │ └── Ex21_03.cpp │ └── Ex21_04 │ │ └── Ex21_04.cpp └── README.md ├── Exercises ├── Appendix A │ ├── SolnA_01 │ │ ├── ASSERT.h │ │ └── SolnA_01.cpp │ ├── SolnA_02 │ │ ├── ASSERT.h │ │ └── SolnA_02.cpp │ ├── SolnA_03 │ │ ├── SmarterException.cpp │ │ ├── SmarterException.h │ │ └── SolnA_03.cpp │ ├── SolnA_04 │ │ ├── SmarterException.h │ │ └── SolnA_04.cpp │ ├── SolnA_05 │ │ ├── Print.cpp │ │ ├── PrintThat.cpp │ │ ├── PrintThat.h │ │ ├── PrintThis.cpp │ │ ├── PrintThis.h │ │ └── SolnA_05.cpp │ ├── SolnA_06 │ │ ├── Print.h │ │ ├── PrintThat.cpp │ │ ├── PrintThat.h │ │ ├── PrintThis.cpp │ │ ├── PrintThis.h │ │ └── SolnA_06.cpp │ ├── SolnA_07A │ │ ├── Print.cpp │ │ ├── PrintThat.cpp │ │ ├── PrintThat.h │ │ ├── PrintThis.cpp │ │ ├── PrintThis.h │ │ └── SolnA_07A.cpp │ └── SolnA_07B │ │ ├── Print.h │ │ ├── PrintThat.cpp │ │ ├── PrintThat.h │ │ ├── PrintThis.cpp │ │ ├── PrintThis.h │ │ └── SolnA_07B.cpp ├── Chapter 01 │ ├── Exer1_03.cpp │ ├── Soln1_01.cpp │ └── Soln1_02.cpp ├── Chapter 02 │ ├── Soln2_01.cpp │ ├── Soln2_02.cpp │ ├── Soln2_03.cpp │ ├── Soln2_04.cpp │ ├── Soln2_05.cpp │ ├── Soln2_06.cpp │ ├── Soln2_07.cpp │ ├── Soln2_08.cpp │ └── Soln2_09.cpp ├── Chapter 03 │ ├── Soln3_01.cpp │ ├── Soln3_02.cpp │ ├── Soln3_03.cpp │ ├── Soln3_04.cpp │ ├── Soln3_05.cpp │ └── Soln3_06.cpp ├── Chapter 04 │ ├── Soln4_01.cpp │ ├── Soln4_02.cpp │ ├── Soln4_03.cpp │ ├── Soln4_04.cpp │ ├── Soln4_05.cpp │ ├── Soln4_06.cpp │ ├── Soln4_07.cpp │ └── Soln4_08.cpp ├── Chapter 05 │ ├── Soln5_01.cpp │ ├── Soln5_02.cpp │ ├── Soln5_03.cpp │ ├── Soln5_04.cpp │ ├── Soln5_05.cpp │ ├── Soln5_06.cpp │ ├── Soln5_07.cpp │ └── Soln5_08.cpp ├── Chapter 06 │ ├── Soln6_01.cpp │ ├── Soln6_02.cpp │ ├── Soln6_03.cpp │ ├── Soln6_04.cpp │ ├── Soln6_05.cpp │ └── Soln6_06.cpp ├── Chapter 07 │ ├── Soln7_01.cpp │ ├── Soln7_02.cpp │ ├── Soln7_03.cpp │ ├── Soln7_04.cpp │ ├── Soln7_05.cpp │ ├── Soln7_06.cpp │ ├── Soln7_07.cpp │ ├── Soln7_08A.cpp │ ├── Soln7_08B.cpp │ ├── Soln7_09A.cpp │ └── Soln7_09B.cpp ├── Chapter 08 │ ├── Soln8_01.cpp │ ├── Soln8_02.cpp │ ├── Soln8_03.cpp │ ├── Soln8_04.cpp │ ├── Soln8_05.cpp │ ├── Soln8_06.cpp │ ├── Soln8_07.cpp │ ├── Soln8_07A.cpp │ ├── Soln8_08.cpp │ └── Soln8_09.cpp ├── Chapter 09 │ ├── Soln9_01.cpp │ ├── Soln9_02.cpp │ ├── Soln9_03.cpp │ ├── Soln9_04.cpp │ ├── Soln9_05.cpp │ └── Soln9_06.cpp ├── Chapter 10 │ ├── Soln10_01.cpp │ ├── Soln10_02.cpp │ ├── Soln10_03.cpp │ ├── Soln10_04.cpp │ ├── Soln10_05.cpp │ └── Soln10_06.cpp ├── Chapter 11 │ ├── Soln11_01 │ │ ├── Soln11_01.cpp │ │ └── words.cppm │ ├── Soln11_02 │ │ ├── Soln11_02.cpp │ │ ├── words.cpp │ │ └── words.cppm │ ├── Soln11_03 │ │ ├── Soln11_03.cpp │ │ ├── words.cppm │ │ ├── words.sorting.cpp │ │ ├── words.sorting.cppm │ │ ├── words.utils.cpp │ │ └── words.utils.cppm │ ├── Soln11_04 │ │ ├── Soln11_04.cpp │ │ ├── internals.cpp │ │ ├── words.cpp │ │ └── words.cppm │ ├── Soln11_05 │ │ ├── Soln11_05.cpp │ │ ├── alias.cppm │ │ ├── internals.cpp │ │ ├── sorting.cppm │ │ ├── utils.cppm │ │ └── words.cppm │ └── Soln11_06 │ │ ├── Soln11_06.cpp │ │ ├── words.cpp │ │ └── words.cppm ├── Chapter 12 │ ├── Soln12_01 │ │ ├── Integer.cpp │ │ ├── Integer.cppm │ │ └── Soln12_01.cpp │ ├── Soln12_02 │ │ ├── Integer.cpp │ │ ├── Integer.cppm │ │ └── Soln12_02.cpp │ ├── Soln12_03 │ │ ├── Integer.cpp │ │ ├── Integer.cppm │ │ └── Soln12_03.cpp │ ├── Soln12_04 │ │ ├── Integer.cpp │ │ ├── Integer.cppm │ │ └── Soln12_04.cpp │ ├── Soln12_05 │ │ ├── Integer.cpp │ │ ├── Integer.cppm │ │ └── Soln12_05.cpp │ ├── Soln12_06 │ │ ├── Integer.cpp │ │ ├── Integer.cppm │ │ └── Soln12_06.cpp │ ├── Soln12_07 │ │ ├── Box.cppm │ │ ├── RandomBoxes.cppm │ │ ├── Soln12_07.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ ├── Soln12_08 │ │ ├── Box.cppm │ │ ├── RandomBoxes.cppm │ │ ├── Soln12_08.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ └── Soln12_09 │ │ ├── Box.cppm │ │ ├── RandomBoxes.cppm │ │ ├── Soln12_09.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm ├── Chapter 13 │ ├── Soln13_01 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Soln13_01.cpp │ ├── Soln13_02 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Soln13_02.cpp │ ├── Soln13_03 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ └── Soln13_03.cpp │ ├── Soln13_04 │ │ ├── Box.cppm │ │ └── Soln13_04.cpp │ ├── Soln13_05 │ │ ├── Box.cppm │ │ └── Soln13_05.cpp │ ├── Soln13_06 │ │ ├── Box.cppm │ │ └── Soln13_06.cpp │ ├── Soln13_07 │ │ ├── Box.cppm │ │ └── Soln13_07.cpp │ ├── Soln13_08 │ │ ├── Rational.cppm │ │ └── Soln13_08.cpp │ ├── Soln13_09 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ ├── PRNG.cppm │ │ └── Soln13_09.cpp │ └── Soln13_10 │ │ ├── Box.cppm │ │ ├── Soln13_10.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm ├── Chapter 14 │ ├── Soln14_01 │ │ ├── Animals.cppm │ │ └── Soln14_01.cpp │ ├── Soln14_02 │ │ ├── Animals.cppm │ │ └── Soln14_02.cpp │ ├── Soln14_03 │ │ ├── Animals.cpp │ │ ├── Animals.cppm │ │ └── Soln14_03.cpp │ └── Soln14_04 │ │ ├── Person.cpp │ │ ├── Person.cppm │ │ └── Soln14_04.cpp ├── Chapter 15 │ ├── Soln15_01 │ │ ├── Animals.cpp │ │ ├── Animals.cppm │ │ ├── Soln15_01.cpp │ │ ├── Zoo.cpp │ │ └── Zoo.cppm │ ├── Soln15_02 │ │ ├── Animals.cpp │ │ ├── Animals.cppm │ │ ├── Soln15_02.cpp │ │ ├── Zoo.cpp │ │ └── Zoo.cppm │ ├── Soln15_03 │ │ ├── Animals.cpp │ │ ├── Animals.cppm │ │ ├── Soln15_03.cpp │ │ ├── Zoo.cpp │ │ └── Zoo.cppm │ ├── Soln15_04 │ │ ├── Animals.cpp │ │ ├── Animals.cppm │ │ ├── Soln15_04.cpp │ │ ├── Zoo.cpp │ │ └── Zoo.cppm │ ├── Soln15_05 │ │ ├── Animals.cpp │ │ ├── Animals.cppm │ │ ├── Soln15_05.cpp │ │ ├── Zoo.cpp │ │ └── Zoo.cppm │ └── Soln15_06 │ │ ├── Point.cppm │ │ ├── Shapes.cppm │ │ └── Soln15_06.cpp ├── Chapter 16 │ ├── Exer16_06 │ │ ├── Customer.cpp │ │ ├── Customer.cppm │ │ ├── DB.cpp │ │ ├── DB.h │ │ ├── DBException.cppm │ │ └── Exer16_06.cpp │ ├── Soln16_01 │ │ ├── Curveball.cppm │ │ └── Soln16_01.cpp │ ├── Soln16_02 │ │ ├── Curveball.cppm │ │ ├── Soln16_02.cpp │ │ └── TooManyExceptions.cppm │ ├── Soln16_03 │ │ ├── Box.cpp │ │ ├── Box.cppm │ │ ├── RandomBoxes.cppm │ │ ├── Soln16_03.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ ├── Soln16_04 │ │ └── Soln16_04.cpp │ ├── Soln16_05 │ │ ├── Curveball.cppm │ │ ├── DomainExceptions.cppm │ │ └── Soln16_05.cpp │ └── Soln16_06 │ │ ├── Customer.cpp │ │ ├── Customer.cppm │ │ ├── DB.cpp │ │ ├── DB.h │ │ ├── DBException.cppm │ │ ├── DB_RAII.cppm │ │ └── Soln16_06.cpp ├── Chapter 17 │ ├── Soln17_01 │ │ ├── Array.cppm │ │ └── Soln17_01.cpp │ ├── Soln17_02 │ │ ├── Pair.cppm │ │ └── Soln17_02.cpp │ ├── Soln17_03 │ │ ├── Soln17_03.cpp │ │ └── SparseArray.cppm │ ├── Soln17_04 │ │ ├── LinkedList.cppm │ │ └── Soln17_04.cpp │ └── Soln17_05 │ │ ├── LinkedList.cppm │ │ ├── Soln17_05.cpp │ │ └── SparseArray.cppm ├── Chapter 18 │ ├── Soln18_01 │ │ ├── Box.cppm │ │ ├── RandomBoxes.cppm │ │ ├── Soln18_01.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ ├── Soln18_02 │ │ ├── LinkedList.cppm │ │ └── Soln18_02.cpp │ ├── Soln18_03 │ │ ├── Customer.cpp │ │ ├── Customer.cppm │ │ ├── DB.cpp │ │ ├── DB.h │ │ ├── DBException.cppm │ │ ├── DB_RAII.cppm │ │ └── Soln18_03.cpp │ ├── Soln18_04 │ │ ├── Customer.cpp │ │ ├── Customer.cppm │ │ ├── DB.cpp │ │ ├── DB.h │ │ ├── DBException.cppm │ │ ├── DB_RAII.cppm │ │ └── Soln18_04.cpp │ └── Soln18_05 │ │ ├── Customer.cpp │ │ ├── Customer.cppm │ │ ├── DB.cpp │ │ ├── DB.h │ │ ├── DBException.cppm │ │ ├── DB_RAII.cppm │ │ └── Soln18_05.cpp ├── Chapter 19 │ ├── Soln19_01 │ │ └── Soln19_01.cpp │ ├── Soln19_02 │ │ ├── Soln19_02.cpp │ │ └── Sort.cppm │ ├── Soln19_03 │ │ ├── BubbleSort.cppm │ │ ├── Quicksort.cppm │ │ ├── Soln19_03.cpp │ │ └── Sort.cppm │ ├── Soln19_04 │ │ ├── Collect.cppm │ │ └── Soln19_04.cpp │ └── Soln19_05 │ │ ├── Box.cppm │ │ ├── DeliveryTruck.cpp │ │ ├── DeliveryTruck.cppm │ │ ├── RandomBoxes.cppm │ │ ├── Soln19_05.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm ├── Chapter 20 │ ├── Soln20_01 │ │ ├── Box.cppm │ │ ├── RandomBoxes.cppm │ │ ├── Soln20_01.cpp │ │ ├── Truckload.cpp │ │ └── Truckload.cppm │ ├── Soln20_02 │ │ └── Soln20_02.cpp │ ├── Soln20_03 │ │ └── Soln20_03.cpp │ ├── Soln20_03A │ │ └── Soln20_03A.cpp │ ├── Soln20_04 │ │ └── Soln20_04.cpp │ ├── Soln20_05 │ │ └── Soln20_05.cpp │ ├── Soln20_06 │ │ └── Soln20_06.cpp │ ├── Soln20_07 │ │ └── Soln20_07.cpp │ ├── Soln20_08 │ │ └── Soln20_08.cpp │ ├── Soln20_09 │ │ └── Soln20_09.cpp │ ├── Soln20_10 │ │ └── Soln20_10.cpp │ ├── Soln20_11 │ │ └── Soln20_11.cpp │ ├── Soln20_12 │ │ └── Soln20_12.cpp │ ├── Soln20_13 │ │ └── Soln20_13.cpp │ ├── Soln20_14 │ │ └── Soln20_14.cpp │ ├── Soln20_15 │ │ ├── Box.cppm │ │ ├── BoxFormatter.cppm │ │ └── Soln20_15.cpp │ ├── Soln20_16 │ │ ├── Box.cppm │ │ ├── BoxFormatter.cppm │ │ └── Soln20_16.cpp │ └── Soln20_17 │ │ ├── Box.cppm │ │ ├── BoxFormatter.cppm │ │ └── Soln20_17.cpp ├── Chapter 21 │ ├── Soln21_01 │ │ └── Soln21_01.cpp │ ├── Soln21_02 │ │ └── Soln21_02.cpp │ ├── Soln21_03 │ │ └── Soln21_03.cpp │ ├── Soln21_04 │ │ └── Soln21_04.cpp │ ├── Soln21_05 │ │ └── Soln21_05.cpp │ └── Soln21_06 │ │ ├── Array.cppm │ │ └── Soln21_06.cpp └── README.md ├── Images ├── CMakeGui.png ├── ConfigureStartupProjects.png ├── MyExercises.png ├── StartupProject.png └── VisualStudio.png ├── LICENSE.txt ├── README.md └── Workarounds ├── Directory.Build.props ├── README.md ├── format_ranges_workaround.h ├── print_workaround.h └── workarounds.h /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/.gitmodules -------------------------------------------------------------------------------- /BeginningCpp23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/BeginningCpp23.jpg -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /Errata.md: -------------------------------------------------------------------------------- 1 | # Errata for *Beginning C++23* 2 | 3 | ## Exercise 20-15: format() must be a const member 4 | 5 | On **page 828**, the correct outline of the `format()` member is as follows: 6 | 7 | ``` 8 | auto format(const Box& box, std::format_context& context) const 9 | { 10 | // ... 11 | } 12 | ``` 13 | 14 | In the book the `const` modifier is missing 15 | (at the time of writing, our compiler was still more forgiving about this mistake). 16 | 17 | 26 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_01/ExA_01.cpp: -------------------------------------------------------------------------------- 1 | // Defining object-like macros 2 | import std; 3 | 4 | #define POINTER_SIZE sizeof(int*) * BITS_PER_BYTE 5 | #define BITS_PER_BYTE 8 6 | 7 | int main() 8 | { 9 | std::println("{}", POINTER_SIZE); // 32 or 64, normally 10 | } 11 | 12 | // The next macro (while providing a perfectly valid definition for "main") 13 | // is never applied, because it is not defined yet when the preprocessor 14 | // processes the line "int main()". 15 | #define main Of chief or leading importance; prime, principal. 16 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_02/ExA_02.cpp: -------------------------------------------------------------------------------- 1 | // Working with preprocessor operators 2 | import std; 3 | 4 | #define DEFINE_PRINT_FUNCTION(NAME, COUNT, VALUE) \ 5 | void NAME##COUNT() { std::println(#VALUE); } 6 | 7 | DEFINE_PRINT_FUNCTION(fun, 123, Test 1 "2" 3) 8 | 9 | int main() 10 | { 11 | fun123(); 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_02A/ExA_02A.cpp: -------------------------------------------------------------------------------- 1 | import std; 2 | 3 | #define DEFINE_PRINT_FUNC\ 4 | TION(NAME, COUNT, VALUE) v\ 5 | oid NAME##COUNT() { std::pr\ 6 | intln(#VALUE); } 7 | 8 | DEFINE_PRINT_FUNCTION(fun, 123, Test 1 "2" 3) 9 | 10 | \ 11 | i\ 12 | nt\ 13 | ma\ 14 | in()\ 15 | {fun1\ 16 | 23();}\ 17 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_03/ExA_03.cpp: -------------------------------------------------------------------------------- 1 | // Using std::source_location, C++'s answer to __LINE__ and __FILE__ 2 | import std; 3 | 4 | void logError(std::string_view errorMessage, 5 | std::source_location location = std::source_location::current()) 6 | { 7 | std::println("{}:{}:{} - An unexpected error occurred in {}: {}", 8 | location.file_name(), location.line(), location.column(), 9 | location.function_name(), errorMessage); 10 | } 11 | 12 | int main() 13 | { 14 | logError("OOPS!"); // The line number in the log message will refer to 15 | // this line in main(), not to the where logError() is defined. 16 | } -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_04/ExA_04.cpp: -------------------------------------------------------------------------------- 1 | // Introducing the #include directive 2 | import std; 3 | 4 | int main() 5 | { 6 | #include "inclusivity.quote" 7 | } 8 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_04/inclusivity.quote: -------------------------------------------------------------------------------- 1 | std::println("We are trying to construct a more inclusive society."); 2 | std::println("We are going to make a country in which no one is left out.\n" 3 | "\t\t\t\t- Franklin D. Roosevelt"); -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_05/ExA_05.cpp: -------------------------------------------------------------------------------- 1 | // Demonstrating assertions 2 | import std; 3 | #include // import ; is not guaranteed to work... 4 | 5 | int main() 6 | { 7 | int y {5}; 8 | 9 | for (int x {}; x < 20; ++x) 10 | { 11 | std::println("x = {}\ty = {}", x, y); 12 | assert(x < y); 13 | } 14 | } 15 | 16 | // A static assertion (comment out to build as a 32-bit program) 17 | static_assert(sizeof(int*) > 4, "32-bit compilation is not supported."); -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_07/ExA_07.cpp: -------------------------------------------------------------------------------- 1 | // Calling external functions 2 | import std; 3 | 4 | double power(double x, int n); // Declaration of an external power() function 5 | 6 | int main() 7 | { 8 | for (int i{ -3 }; i <= 3; ++i) // Calculate powers of 8 from -3 to +3 9 | std::println("{:10}", power(8.0, i)); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_07/Power.cpp: -------------------------------------------------------------------------------- 1 | // The power function called from ExA_07.cpp is defined in a different translation unit 2 | double power(double x, int n) 3 | { 4 | if (n < 0) return 1.0 / power(x, -n); // Deal with negative exponents 5 | if (n == 0) return 1.0; // Recursion base case 6 | const double y{ power(x, n / 2) }; // See Exercise 8-8 for an explanation 7 | return y * y * (n % 2 == 1 ? x : 1.0); 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_07A/ExA_07A.cpp: -------------------------------------------------------------------------------- 1 | // Calling external functions that are declared in a header file 2 | import std; 3 | #include "Power.h" 4 | 5 | int main() 6 | { 7 | for (int i {-3}; i <= 3; ++i) // Calculate powers of 8 from -3 to +3 8 | std::println("{:10}", power(8.0, i)); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_07A/Power.cpp: -------------------------------------------------------------------------------- 1 | // The power function called from ExA_07A.cpp is defined in a different translation unit 2 | double power(double x, int n) 3 | { 4 | if (n < 0) return 1.0 / power(x, -n); // Deal with negative exponents 5 | if (n == 0) return 1.0; // Recursion base case 6 | const double y{ power(x, n / 2) }; // See Exercise 8-8 for an explanation 7 | return y * y * (n % 2 == 1 ? x : 1.0); 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_07A/Power.h: -------------------------------------------------------------------------------- 1 | // Your first header file containing a declaration of an external power() function 2 | double power(double x, int n); 3 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_08/ExA_08.cpp: -------------------------------------------------------------------------------- 1 | // Using an externally defined variable 2 | import std; 3 | 4 | /*extern*/ double power(double x, int n); // Declaration of an external power() function 5 | /*extern*/ int power_range; // Not an unreasonable first attempt, right? 6 | 7 | int main() 8 | { 9 | for (int i {-power_range}; i <= power_range; ++i) // Calculate powers of 8 10 | std::println("{:10}", power(8.0, i)); 11 | } 12 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_08/Power.cpp: -------------------------------------------------------------------------------- 1 | // The power function called from ExA_08.cpp is defined in a different translation unit 2 | double power(double x, int n) 3 | { 4 | if (n < 0) return 1.0 / power(x, -n); // Deal with negative exponents 5 | if (n == 0) return 1.0; // Recursion base case 6 | const double y{ power(x, n / 2) }; // See Exercise 8-8 for an explanation 7 | return y * y * (n % 2 == 1 ? x : 1.0); 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_08/Range.cpp: -------------------------------------------------------------------------------- 1 | int power_range{ 3 }; // A global variable with external linkage -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_08A/ExA_08A.cpp: -------------------------------------------------------------------------------- 1 | // Using an externally defined constant 2 | import std; 3 | 4 | extern double power(double x, int n); // Declaration of an external power() function 5 | extern const int power_range; // Declaration of an external global constant 6 | 7 | int main() 8 | { 9 | for (int i {-power_range}; i <= power_range; ++i) // Calculate powers of 8 10 | std::println("{:10}", power(8.0, i)); 11 | } 12 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_08A/Power.cpp: -------------------------------------------------------------------------------- 1 | // The power function called from ExA_08A.cpp is defined in a different translation unit 2 | double power(double x, int n) 3 | { 4 | if (n < 0) return 1.0 / power(x, -n); // Deal with negative exponents 5 | if (n == 0) return 1.0; // Recursion base case 6 | const double y{ power(x, n / 2) }; // See Exercise 8-8 for an explanation 7 | return y * y * (n % 2 == 1 ? x : 1.0); 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_08A/Range.cpp: -------------------------------------------------------------------------------- 1 | extern const int power_range{ 3 }; // Definition of a global constant with external linkage -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_09/ExA_09.cpp: -------------------------------------------------------------------------------- 1 | // Using a local helper function with internal linkage (see Power.cpp) 2 | import std; 3 | 4 | extern double power(double x, int n); // Declaration of an external power() function 5 | 6 | int main() 7 | { 8 | for (int i{ -3 }; i <= 3; ++i) // Calculate powers of 8 9 | std::println("{:10}", power(8.0, i)); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_09/Power.cpp: -------------------------------------------------------------------------------- 1 | // A local helper function with internal linkage 2 | namespace 3 | { 4 | double localHelper(double x, unsigned n) // localHelper() has internal linkage 5 | { 6 | if (n == 0) return 1.0; // Recursion base case 7 | const double y{ localHelper(x, n / 2) }; // See Exercise 8-8 for an explanation 8 | return y * y * (n % 2 == 1 ? x : 1.0); 9 | } 10 | } 11 | 12 | double power(double x, int n) // power() has external linkage 13 | { 14 | return n >= 0 ? localHelper(x, static_cast(n)) 15 | : 1.0 / localHelper(x, static_cast(-n)); 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_09A/ExA_09A.cpp: -------------------------------------------------------------------------------- 1 | // Attempting to call a function with internal linkage from a different translation unit 2 | import std; 3 | 4 | double localHelper(double x, unsigned n); // Declares an external localHelper() function 5 | 6 | int main() 7 | { 8 | for (unsigned i{ 0 }; i <= 5; ++i) // Calculate positive powers of 8 9 | std::println("{:10}", localHelper(8.0, i)); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_09A/Power.cpp: -------------------------------------------------------------------------------- 1 | // A local helper function with internal linkage 2 | namespace 3 | { 4 | double localHelper(double x, unsigned n) // localHelper() has internal linkage 5 | { 6 | if (n == 0) return 1.0; // Recursion base case 7 | const double y{ localHelper(x, n / 2) }; // See Exercise 8-8 for an explanation 8 | return y * y * (n % 2 == 1 ? x : 1.0); 9 | } 10 | } 11 | 12 | double power(double x, int n) // power() has external linkage 13 | { 14 | return n >= 0 ? localHelper(x, static_cast(n)) 15 | : 1.0 / localHelper(x, static_cast(-n)); 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_10/BadMath.h: -------------------------------------------------------------------------------- 1 | auto square(const auto& x) { return x * x; } // An abbreviated function template 2 | 3 | const double lambda{ 1.303577269034296391257 }; // Conway's constant 4 | 5 | enum class Oddity { Even, Odd }; 6 | bool isOdd(int x) { return x % 2 != 0; } 7 | auto getOddity(int x) { return isOdd(x) ? Oddity::Odd : Oddity::Even; } 8 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_10/ExA_10.cpp: -------------------------------------------------------------------------------- 1 | // Including the same definitions twice 2 | import std; 3 | #include "BadMath.h" 4 | #include "BadMath.h" 5 | 6 | int main() 7 | { 8 | std::println("{}", square(1.234)); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_10A/BetterMath.h: -------------------------------------------------------------------------------- 1 | // A second, better attempt at creating a header file 2 | #ifndef BETTER_MATH_H 3 | #define BETTER_MATH_H 4 | 5 | auto square(const auto& x) { return x * x; } // An abbreviated function template 6 | 7 | const double lambda{ 1.303577269034296391257 }; // Conway's constant 8 | 9 | enum class Oddity { Even, Odd }; 10 | bool isOdd(int x) { return x % 2 != 0; } 11 | auto getOddity(int x) { return isOdd(x) ? Oddity::Odd : Oddity::Even; } 12 | 13 | #endif -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_10A/ExA_10A.cpp: -------------------------------------------------------------------------------- 1 | // Including the same header twice in the same translation unit without violating ODR 2 | import std; 3 | #include "BetterMath.h" 4 | #include "BetterMath.h" 5 | 6 | int main() 7 | { 8 | std::println("{}", square(1.234)); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_11/BetterMath.h: -------------------------------------------------------------------------------- 1 | // A second, better attempt at creating a header file 2 | #ifndef BETTER_MATH_H 3 | #define BETTER_MATH_H 4 | 5 | auto square(const auto& x) { return x * x; } // An abbreviated function template 6 | 7 | const double lambda{ 1.303577269034296391257 }; // Conway's constant 8 | 9 | enum class Oddity { Even, Odd }; 10 | bool isOdd(int x) { return x % 2 != 0; } 11 | auto getOddity(int x) { return isOdd(x) ? Oddity::Odd : Oddity::Even; } 12 | 13 | #endif -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_11/ExA_11.cpp: -------------------------------------------------------------------------------- 1 | // Creating multiple definitions of the same functions in a program, 2 | // even though #include guards are present. 3 | // (The guards only prevent multiple definitions within one translation unit!) 4 | import std; 5 | #include "Hypot.h" 6 | #include "Pow4.h" 7 | 8 | int main() 9 | { 10 | std::println("{}\t{}", math::hypot(3, 4), math::pow4(5)); 11 | } 12 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_11/Hypot.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Examples/Appendix A/ExA_11/Hypot.cpp -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_11/Hypot.h: -------------------------------------------------------------------------------- 1 | // Declaration of an external math::hypot() function 2 | #ifndef HYPOT_H 3 | #define HYPOT_H 4 | 5 | namespace math 6 | { 7 | // Computes the length of the hypotenuse of a right-angle triangle 8 | double hypot(double x, double y); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_11/Pow4.cpp: -------------------------------------------------------------------------------- 1 | // Definition of the math::pow4() function 2 | #include "BetterMath.h" // For the square() function template definition 3 | 4 | namespace math 5 | { 6 | double pow4(double x) { return square(square(x)); } 7 | } 8 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_11/Pow4.h: -------------------------------------------------------------------------------- 1 | // Declaration of a math::pow4() function 2 | #ifndef POW4_H 3 | #define POW4_H 4 | 5 | namespace math 6 | { 7 | // Same as std::pow(x, 4) 8 | double pow4(double x); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_12/ExA_12.cpp: -------------------------------------------------------------------------------- 1 | // Using inline definitions to prevent ODR violations when 2 | // including a header in multiple translation units of the same program. 3 | import std; 4 | #include "Hypot.h" 5 | #include "Pow4.h" 6 | 7 | int main() 8 | { 9 | std::println("{}\t{}", math::hypot(3, 4), math::pow4(5)); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_12/Hypot.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Examples/Appendix A/ExA_12/Hypot.cpp -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_12/Hypot.h: -------------------------------------------------------------------------------- 1 | // Declaration of an external math::hypot() function 2 | #ifndef HYPOT_H 3 | #define HYPOT_H 4 | 5 | namespace math 6 | { 7 | // Computes the length of the hypotenuse of a right-angle triangle 8 | double hypot(double x, double y); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_12/Pow4.cpp: -------------------------------------------------------------------------------- 1 | // Definition of the math::pow4() function 2 | #include "ProperMath.h" // For the square() function template definition 3 | 4 | namespace math 5 | { 6 | double pow4(double x) { return square(square(x)); } 7 | } 8 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_12/Pow4.h: -------------------------------------------------------------------------------- 1 | // Declaration of a math::pow4() function 2 | #ifndef POW4_H 3 | #define POW4_H 4 | 5 | namespace math 6 | { 7 | // Same as std::pow(x, 4) 8 | double pow4(double x); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_12/ProperMath.h: -------------------------------------------------------------------------------- 1 | // Your first, proper header file 2 | #ifndef PROPER_MATH_H 3 | #define PROPER_MATH_H 4 | 5 | auto square(const auto& x) { return x * x; } // An abbreviated function template 6 | 7 | const inline double lambda{ 1.303577269034296391257 }; // Conway's constant 8 | 9 | enum class Oddity { Even, Odd }; 10 | inline bool isOdd(int x) { return x % 2 != 0; } 11 | inline auto getOddity(int x) { return isOdd(x) ? Oddity::Odd : Oddity::Even; } 12 | 13 | #endif -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_13/Box.cpp: -------------------------------------------------------------------------------- 1 | #include "Box.h" 2 | 3 | Box::Box() : Box{ 1.0, 1.0, 1.0 } {} 4 | Box::Box(double length, double width, double height) 5 | : m_length{ length }, m_width{ width }, m_height{ height } 6 | {} 7 | 8 | double Box::getLength() const { return m_length; } 9 | double Box::getWidth() const { return m_width; } 10 | double Box::getHeight() const { return m_height; } 11 | 12 | double Box::volume() const 13 | { 14 | return m_length * m_width * m_height; 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_13/Box.h: -------------------------------------------------------------------------------- 1 | // Your first header file with a class definition 2 | #ifndef BOX_H 3 | #define BOX_H 4 | 5 | class Box 6 | { 7 | public: 8 | Box(); 9 | Box(double length, double width, double height); 10 | 11 | double getLength() const; 12 | double getWidth() const; 13 | double getHeight() const; 14 | 15 | double volume() const; 16 | 17 | private: 18 | double m_length; 19 | double m_width; 20 | double m_height; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_13/ExA_13.cpp: -------------------------------------------------------------------------------- 1 | // Including a class definition from a header 2 | import std; 3 | #include "Box.h" 4 | 5 | int main() 6 | { 7 | Box boxy{ 1, 2, 3 }; 8 | std::println("{}", boxy.volume()); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Appendix A/ExA_13A/ExA_13A.cpp: -------------------------------------------------------------------------------- 1 | // Inline class member definitions (see Box.h) 2 | import std; 3 | #include "Box.h" 4 | 5 | int main() 6 | { 7 | Box boxy{ 1, 2, 3 }; 8 | std::println("{}", boxy.volume()); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 01/Ex1_01.cpp: -------------------------------------------------------------------------------- 1 | // A complete C++ program 2 | import std; // This line makes the entire Standard Library available, 3 | // including the std::println() functionality used below 4 | int main() 5 | { 6 | int answer {42}; // Defines the variable answer with value 42 7 | std::println("The answer to life, the universe, and everything is {}.", answer); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 02/Ex2_01.cpp: -------------------------------------------------------------------------------- 1 | // Writing values of variables to the screen 2 | import std; 3 | 4 | int main() 5 | { 6 | int apple_count {15}; // Number of apples 7 | int orange_count {5}; // Number of oranges 8 | int total_fruit {apple_count + orange_count}; // Total number of fruit 9 | 10 | std::println("The value of apple_count is {}", apple_count); 11 | std::println("The value of orange_count is {}", orange_count); 12 | std::println("The value of total_fruit is {}", total_fruit); 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Chapter 02/Ex2_06.cpp: -------------------------------------------------------------------------------- 1 | // Using escape sequences 2 | import std; 3 | 4 | int main() 5 | { 6 | std::println("\"Least \'said\' \\\n\t\tsoonest \'mended\'.\""); 7 | } 8 | -------------------------------------------------------------------------------- /Examples/Chapter 02/Ex2_07.cpp: -------------------------------------------------------------------------------- 1 | // The width, alignment, fill, and 0 formatting options of std::println() 2 | import std; 3 | 4 | int main() 5 | { 6 | // Default alignment: right for numbers, left otherwise 7 | std::println("{:7}|{:7}|{:7}|{:7}", 1, -.2, "str", 'c'); 8 | // Left and right alignment + custom fill character 9 | std::println("{:*<7}|{:*<7}|{:*>7}|{:*>7}", 1, -.2, "str", 'c'); 10 | // 0 formatting option for numbers + centered alignment 11 | std::println("{:07}|{:07}|{:^7}|{:^7}", 1, -.2, "str", 'c'); 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 02/Ex2_08.cpp: -------------------------------------------------------------------------------- 1 | // Formatting numeric values with std::println() 2 | import std; 3 | 4 | int main() 5 | { 6 | const double pi{ std::numbers::pi }; 7 | std::println("Default: {:.2}, fixed: {:.2f}, scientific: {:.2e}, general: {:.2g}", 8 | pi, pi, pi, pi); 9 | std::println("Default: {}, binary: {:b}, hex.: {:x}", 314, 314, 314); 10 | std::println("Default: {}, decimal: {:d}, hex.: {:x}", 'c', 'c', 'c'); 11 | std::println("Alternative hex.: {:#x}, binary: {:#b}, HEX.: {:#X}", 314, 314, 314); 12 | std::println("Forced sign: {:+}, space sign: {: }", 314, 314); 13 | std::println("All together: {:*<+10.4f}, {:+#09x}", pi, 314); 14 | } -------------------------------------------------------------------------------- /Examples/Chapter 02/Ex2_08A.cpp: -------------------------------------------------------------------------------- 1 | // Argument indices for std::println() 2 | import std; 3 | 4 | int main() 5 | { 6 | const double pi{ std::numbers::pi }; 7 | std::println("Default: {0:.2}, fixed: {0:.2f}, scientific: {0:.2e}, general: {0:.2g}", pi); 8 | std::println("Default: {0}, binary: {0:b}, hex.: {0:x}", 314); 9 | std::println("Default: {0}, decimal: {0:d}, hex.: {0:x}", 'c'); 10 | std::println("Alternative hex.: {0:#x}, binary: {0:#b}, HEX.: {0:#X}", 314); 11 | std::println("Forced sign: {0:+}, space sign: {0: }", 314); 12 | std::println("All together: {0:*<+10.4f}, {1:+#09x}", pi, 314); 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_01.cpp: -------------------------------------------------------------------------------- 1 | // Comparing data values 2 | import std; 3 | 4 | int main() 5 | { 6 | char first {}; // Stores the first character 7 | char second {}; // Stores the second character 8 | 9 | std::print("Enter a character: "); 10 | std::cin >> first; 11 | 12 | std::print("Enter a second character: "); 13 | std::cin >> second; 14 | 15 | std::println("The value of the expression {} < {} is {}", 16 | first, second, first < second); 17 | std::println("The value of the expression {} == {} is {}", 18 | first, second, first == second); 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_02.cpp: -------------------------------------------------------------------------------- 1 | // Three-way comparison of integers 2 | import std; // Required also for using operator <=> (even for fundamental types) 3 | 4 | int main() 5 | { 6 | std::print("Please enter a number: "); 7 | int value; 8 | std::cin >> value; 9 | 10 | std::strong_ordering ordering{ value <=> 0 }; 11 | 12 | std::println("value < 0: {}", ordering == std::strong_ordering::less); 13 | std::println("value > 0: {}", ordering == std::strong_ordering::greater); 14 | std::println("value == 0: {}", ordering == std::strong_ordering::equal); 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_02A.cpp: -------------------------------------------------------------------------------- 1 | // Using the named comparison functions 2 | import std; 3 | 4 | int main() 5 | { 6 | std::print("Please enter a number: "); 7 | 8 | int value; 9 | std::cin >> value; 10 | 11 | std::strong_ordering ordering{ value <=> 0 }; 12 | 13 | std::println("value < 0: {}", std::is_lt(ordering)); // is less than 14 | std::println("value > 0: {}", std::is_gt(ordering)); // is greater than 15 | std::println("value == 0: {}", std::is_eq(ordering)); // is equivalent 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_03.cpp: -------------------------------------------------------------------------------- 1 | // Using an if statement 2 | import std; 3 | 4 | int main() 5 | { 6 | std::print("Enter an integer between 50 and 100: "); 7 | int value {}; 8 | std::cin >> value; 9 | 10 | if (value) 11 | std::println("You have entered a value that is different from zero."); 12 | 13 | if (value < 50) 14 | std::println("The value is invalid - it is less than 50."); 15 | 16 | if (value > 100) 17 | std::println("The value is invalid - it is greater than 100."); 18 | 19 | std::println("You entered {}.", value); 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_04A.cpp: -------------------------------------------------------------------------------- 1 | // Using the std::isupper() / islower() character classification functions 2 | import std; 3 | 4 | int main() 5 | { 6 | char letter {}; // Store input here 7 | std::print("Enter a letter: "); // Prompt for the input 8 | std::cin >> letter; 9 | 10 | if (std::isupper(letter)) 11 | { 12 | std::println("You entered an uppercase letter."); 13 | return 0; 14 | } 15 | 16 | if (std::islower(letter)) 17 | { 18 | std::println("You entered an lowercase letter."); 19 | return 0; 20 | } 21 | 22 | std::println("You did not enter a letter."); 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_05.cpp: -------------------------------------------------------------------------------- 1 | // Using the if-else statement 2 | import std; 3 | 4 | int main() 5 | { 6 | long number {}; // Stores input 7 | std::print("Enter an integer less than 2 billion: "); 8 | std::cin >> number; 9 | 10 | if (number % 2) // Test remainder after division by 2 11 | { // Here if remainder is 1 12 | std::println("Your number is odd."); 13 | } 14 | else 15 | { // Here if remainder is 0 16 | std::println("Your number is even."); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_07.cpp: -------------------------------------------------------------------------------- 1 | // Using the conditional operator to select output. 2 | import std; 3 | 4 | int main() 5 | { 6 | int mice {}; // Count of all mice 7 | int brown {}; // Count of brown mice 8 | int white {}; // Count of white mice 9 | 10 | std::print("How many brown mice do you have? "); 11 | std::cin >> brown; 12 | std::print("How many white mice do you have? "); 13 | std::cin >> white; 14 | 15 | mice = brown + white; 16 | 17 | std::println("You have {} {} in total.", mice, mice == 1 ? "mouse" : "mice"); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_09.cpp: -------------------------------------------------------------------------------- 1 | // Multiple case actions 2 | import std; 3 | 4 | int main() 5 | { 6 | char letter {}; 7 | std::print("Enter a letter: "); 8 | std::cin >> letter; 9 | 10 | if (std::isalpha(letter)) 11 | { 12 | switch (std::tolower(letter)) 13 | { 14 | case 'a': case 'e': case 'i': case 'o': case 'u': 15 | std::println("You entered a vowel."); 16 | break; 17 | default: 18 | std::println("You entered a consonant."); 19 | break; 20 | } 21 | } 22 | else 23 | { 24 | std::println("You did not enter a letter."); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_09A.cpp: -------------------------------------------------------------------------------- 1 | // Using a return statement to exit a switch statement 2 | import std; 3 | 4 | int main() 5 | { 6 | char letter {}; 7 | std::print("Enter a letter: "); 8 | std::cin >> letter; 9 | 10 | if (std::isalpha(letter)) 11 | { 12 | switch (std::tolower(letter)) 13 | { 14 | case 'a': case 'e': case 'i': case 'o': case 'u': 15 | std::println("You entered a vowel."); 16 | return 0; // Ends the program 17 | } 18 | 19 | // We did not exit main() in the above switch, so letter is not a vowel: 20 | std::println("You entered a consonant."); 21 | } 22 | else 23 | { 24 | std::println("You did not enter a letter."); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/Chapter 04/Ex4_10.cpp: -------------------------------------------------------------------------------- 1 | // Switching on enumerations 2 | import std; 3 | 4 | int main() 5 | { 6 | enum class Color { red, green, blue }; 7 | 8 | Color my_color = Color::red; 9 | 10 | std::print("Today, I'm feeling "); 11 | switch (my_color) 12 | { 13 | case Color::red: std::println("loving"); break; 14 | case Color::green: std::println("jealous"); break; 15 | case Color::blue: std::println("sad"); break; 16 | } 17 | } -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_02.cpp: -------------------------------------------------------------------------------- 1 | // Obtaining the number of array elements 2 | import std; 3 | 4 | int main() 5 | { 6 | int values[] {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 7 | 8 | std::println("There are {} elements in the array.", std::size(values)); 9 | 10 | int sum {}; 11 | const std::size_t old_school_size = sizeof(values) / sizeof(values[0]); 12 | for (std::size_t i {}; i < old_school_size; ++i) 13 | { 14 | sum += values[i]; 15 | } 16 | std::println("The sum of the array elements is {}.", sum); 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_03.cpp: -------------------------------------------------------------------------------- 1 | // Floating-point control in a for loop 2 | import std; 3 | 4 | int main() 5 | { 6 | const unsigned values_per_line {3}; // Outputs per line 7 | unsigned values_current_line {}; // Number of outputs on current line 8 | for (double radius {0.2}; radius <= 3.0; radius += 0.2) 9 | { 10 | const auto area{ std::numbers::pi * radius * radius }; 11 | std::print("radius = {:4.2f}, area = {:5.2f}; ", radius, area); 12 | if (++values_current_line == values_per_line) // When enough values written... 13 | { 14 | std::println(""); // ...start a new line... 15 | values_current_line = 0; // ...and reset the line counter 16 | } 17 | } 18 | std::println(""); 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_03A.cpp: -------------------------------------------------------------------------------- 1 | // Floating-point control in a for loop: 2 | // dangers of floating-point representation errors. 3 | import std; 4 | 5 | int main() 6 | { 7 | for (double radius{ 0.2 }; radius <= 3.0; radius += 0.2) 8 | { 9 | std::println("radius = {:4.2f}, area = {:5.2f}, (radius + 0.2) = 3.0 + {}", 10 | radius, 11 | std::numbers::pi * radius * radius, 12 | (radius + 0.2) - 3.0 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_03B.cpp: -------------------------------------------------------------------------------- 1 | // Floating-point control in a for loop 2 | import std; 3 | 4 | int main() 5 | { 6 | const unsigned values_per_line {3}; // Outputs per line 7 | unsigned values_current_line {}; // Number of outputs on current line 8 | for (double radius {0.2}; radius < 3.0 + 0.001; radius += 0.2) 9 | { 10 | const auto area{ std::numbers::pi * radius * radius }; 11 | std::print("radius = {:4.2f}, area = {:5.2f}; ", radius, area); 12 | if (++values_current_line == values_per_line) // When enough values written... 13 | { 14 | std::println(""); // ...start a new line... 15 | values_current_line = 0; // ...and reset the line counter 16 | } 17 | } 18 | std::println(""); 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_04.cpp: -------------------------------------------------------------------------------- 1 | // Multiple initializations in a loop expression 2 | import std; 3 | 4 | int main() 5 | { 6 | unsigned int limit {}; 7 | std::print("This program calculates n! and the sum of the integers up to n "); 8 | std::print("for values 1 to limit.\nWhat upper limit for n would you like? "); 9 | std::cin >> limit; 10 | 11 | // Output column headings 12 | std::println("{:>8} {:>8} {:>20}", "integer", "sum", "factorial"); 13 | 14 | for (unsigned long long n {1}, sum {}, factorial {1}; n <= limit; ++n) 15 | { 16 | sum += n; // Accumulate sum to current n 17 | factorial *= n; // Calculate n! for current n 18 | std::println("{:8} {:8} {:20}", n, sum, factorial); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_04A.cpp: -------------------------------------------------------------------------------- 1 | // Multiple calculations in a loop expression's third control expression 2 | // by using the comma operator 3 | import std; 4 | 5 | int main() 6 | { 7 | unsigned int limit {}; 8 | std::print("This program calculates n! and the sum of the integers up to n "); 9 | std::print("for values 1 to limit.\nWhat upper limit for n would you like? "); 10 | std::cin >> limit; 11 | 12 | // Output column headings 13 | std::println("{:>8} {:>8} {:>20}", "integer", "sum", "factorial"); 14 | 15 | for (unsigned long long n {1}, sum {1}, factorial {1}; n <= limit; 16 | ++n, sum += n, factorial *= n) 17 | { 18 | std::println("{:8} {:8} {:20}", n, sum, factorial); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_08.cpp: -------------------------------------------------------------------------------- 1 | // Using the continue statement to display ASCII character codes 2 | import std; 3 | 4 | int main() 5 | { 6 | // 3 cols., 11 wide, centered (^) 7 | std::println("{:^11}{:^11}{:^11}", "Character", "Hexadecimal", "Decimal"); 8 | 9 | // Output 7-bit ASCII characters and corresponding codes 10 | for (int ch {}; ch <= 127; ++ch) 11 | { 12 | if (!std::isprint(ch)) // If it's not printable... 13 | continue; // ...skip this iteration 14 | std::println("{0:^11}{0:^11X}{0:^11d}", static_cast(ch)); // Print 3 times 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 05/Ex5_16.cpp: -------------------------------------------------------------------------------- 1 | // Format specifiers for containers 2 | import std; 3 | 4 | int main() 5 | { 6 | std::vector v{ 1, 2, 3, 4 }; // Deduced type: std::vector 7 | std::println("Default formatting: {}", v); // [1, 2, 3, 4] 8 | std::println("No braces: {:n}", v); // 1, 2, 3, 4 9 | std::println("Curly braces: {{{:n}}}", v); // {1, 2, 3, 4} 10 | std::println("Format range only: {:*^20}", v); // ****[1, 2, 3, 4]**** 11 | std::println("Format elements only: {::*<3}", v); // [1**, 2**, 3**, 4**] 12 | std::println("All at once: {:*^20n:03b}", v); // *001, 010, 011, 100* 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Chapter 06/Ex6_01.cpp: -------------------------------------------------------------------------------- 1 | // The size of pointers 2 | import std; 3 | 4 | int main() 5 | { 6 | // Print out the size (in number of bytes) of some data types 7 | // and the corresponding pointer types: 8 | std::println("{} > {}", sizeof(double), sizeof(char16_t)); 9 | std::println("{} == {}", sizeof(double*), sizeof(char16_t*)); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Chapter 06/Ex6_04.cpp: -------------------------------------------------------------------------------- 1 | // Using an array of pointers 2 | import std; 3 | 4 | int main() 5 | { 6 | const char* pstars[] { 7 | "Fatty Arbuckle", "Clara Bow", "Lassie", 8 | "Slim Pickens", "Boris Karloff", "Mae West", 9 | "Oliver Hardy", "Greta Garbo" 10 | }; 11 | 12 | std::print("Pick a lucky star! Enter a number between 1 and {}: ", std::size(pstars)); 13 | unsigned choice {}; 14 | std::cin >> choice; 15 | 16 | if (choice >= 1 && choice <= std::size(pstars)) 17 | { 18 | std::println("Your lucky star is {}.", pstars[choice - 1]); 19 | } 20 | else 21 | { 22 | std::println("Sorry, you haven't got a lucky star."); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Examples/Chapter 07/Ex7_04.cpp: -------------------------------------------------------------------------------- 1 | // Searching within strings 2 | import std; 3 | 4 | int main() 5 | { 6 | std::string sentence {"Manners maketh man"}; 7 | std::string word {"man"}; 8 | std::println("{}", sentence.find(word)); // Prints 15 9 | std::println("{}", sentence.find("Ma")); // Prints 0 10 | std::println("{}", sentence.find('k')); // Prints 10 11 | std::println("{}", sentence.find('x')); // Prints std::string::npos 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_01.cpp: -------------------------------------------------------------------------------- 1 | // Calculating powers 2 | import std; 3 | 4 | // Function to calculate x to the power n 5 | double power(double x, int n) 6 | { 7 | double result{ 1.0 }; 8 | if (n >= 0) 9 | { 10 | for (int i{ 1 }; i <= n; ++i) 11 | result *= x; 12 | } 13 | else // n < 0 14 | { 15 | for (int i{ 1 }; i <= -n; ++i) 16 | result /= x; 17 | } 18 | return result; 19 | } 20 | 21 | int main() 22 | { 23 | // Calculate powers of 8 from -3 to +3 24 | for (int i{ -3 }; i <= 3; ++i) 25 | std::print("{:10g}", power(8.0, i)); 26 | 27 | std::println(""); 28 | } 29 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_02.cpp: -------------------------------------------------------------------------------- 1 | // Calculating powers - rearranged 2 | import std; 3 | 4 | //double power(double x, int n); // Function prototype - uncomment for successful compilation 5 | 6 | int main() 7 | { 8 | // Calculate powers of 8 from -3 to +3 9 | for (int i {-3}; i <= 3; ++i) 10 | std::print("{:10g}", power(8.0, i)); 11 | 12 | std::println(""); 13 | } 14 | 15 | // Function to calculate x to the power n 16 | double power(double x, int n) 17 | { 18 | double result{ 1.0 }; 19 | if (n >= 0) 20 | { 21 | for (int i{ 1 }; i <= n; ++i) 22 | result *= x; 23 | } 24 | else // n < 0 25 | { 26 | for (int i{ 1 }; i <= -n; ++i) 27 | result /= x; 28 | } 29 | return result; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_03.cpp: -------------------------------------------------------------------------------- 1 | // Failing to modify the original value of a function argument 2 | import std; 3 | 4 | double changeIt(double value_to_be_changed); // Function prototype 5 | 6 | int main() 7 | { 8 | double it {5.0}; 9 | double result {changeIt(it)}; 10 | 11 | std::println("After function execution, it = {}", it); 12 | std::println("Result returned is {}", result); 13 | } 14 | 15 | // Function that attempts to modify an argument and return it 16 | double changeIt(double it) 17 | { 18 | it += 10.0; // This modifies the copy 19 | std::println("Within function, it = {}", it); 20 | return it; 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_04.cpp: -------------------------------------------------------------------------------- 1 | // Modifying the value of a caller variable 2 | import std; 3 | 4 | double changeIt(double* pointer_to_it); // Function prototype 5 | 6 | int main() 7 | { 8 | double it {5.0}; 9 | double result {changeIt(&it)}; // Now we pass the address 10 | 11 | std::println("After function execution, it = {}", it); 12 | std::println("Result returned is {}", result); 13 | } 14 | 15 | // Function to modify an argument and return it 16 | double changeIt(double* pit) 17 | { 18 | *pit += 10.0; // This modifies the original double 19 | std::println("Within function, *pit = {}", *pit); 20 | return *pit; 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_05.cpp: -------------------------------------------------------------------------------- 1 | // Passing an array to a function 2 | import std; 3 | 4 | double average(double array[], std::size_t count); // Function prototype 5 | 6 | int main() 7 | { 8 | double values[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}; 9 | std::println("Average = {}", average(values, std::size(values))); 10 | } 11 | 12 | // Function to compute an average 13 | double average(double array[], std::size_t count) 14 | { 15 | double sum {}; // Accumulate total in here 16 | for (std::size_t i {}; i < count; ++i) 17 | sum += array[i]; // Sum array elements 18 | return sum / count; // Return average 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_07.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Examples/Chapter 08/Ex8_07.cpp -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_09B.cpp: -------------------------------------------------------------------------------- 1 | // Passing an array to a function - pass by reference improved 2 | import std; 3 | 4 | double average10(const double (&)[10]); // Function prototype 5 | 6 | int main() 7 | { 8 | double values[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; 9 | // double values[] { 1.0, 2.0, 3.0 }; // Only three values!!! 10 | std::println("Average = {}", average10(values)); 11 | } 12 | 13 | // Function to compute an average 14 | double average10(const double (&array)[10]) 15 | { 16 | double sum {}; // Accumulate total in here 17 | for (double val : array) 18 | sum += val; // Sum array elements 19 | return sum / std::size(array); // Return average 20 | } -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_10.cpp: -------------------------------------------------------------------------------- 1 | // Implicit conversions of reference parameters 2 | import std; 3 | 4 | void double_it(double& it) { it *= 2; } 5 | void print_it(const double& it) { std::println("{}", it); } 6 | 7 | int main() 8 | { 9 | double d{123}; 10 | double_it(d); 11 | print_it(d); 12 | 13 | int i{456}; 14 | // double_it(i); /* error, does not compile! */ 15 | print_it(i); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_12.cpp: -------------------------------------------------------------------------------- 1 | // Program that lists its command line arguments 2 | import std; 3 | 4 | int main(int argc, char* argv[]) 5 | { 6 | for (int i{}; i < argc; ++i) 7 | std::println("{}", argv[i]); 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_16.cpp: -------------------------------------------------------------------------------- 1 | // Recursive version of function for x to the power n, n positive or negative 2 | import std; 3 | 4 | double power(double x, int n); 5 | 6 | int main() 7 | { 8 | for (int i{ -3 }; i <= 3; ++i) // Calculate powers of 8 from -3 to +3 9 | std::print("{:10g}", power(8.0, i)); 10 | 11 | std::println(""); 12 | } 13 | 14 | // Recursive function to calculate x to the power n 15 | double power(double x, int n) 16 | { 17 | if (n == 0) return 1.0; 18 | else if (n > 0) return x * power(x, n - 1); 19 | else /* n < 0 */ return 1.0 / power(x, -n); 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Chapter 08/Ex8_19B.cpp: -------------------------------------------------------------------------------- 1 | // Constant expressions 2 | 3 | import std; 4 | 5 | constexpr int sqrt(int x) 6 | { 7 | #ifdef __cpp_if_consteval // Conditional compilation depending on whether consteval if statements are supported (see Appendix A) 8 | if consteval 9 | #else 10 | if (std::is_constant_evaluated()) 11 | #endif 12 | { 13 | int result{}; 14 | while (result * result <= x) ++result; 15 | return result - 1; 16 | } 17 | else 18 | { 19 | return static_cast(std::sqrt(x)); // Only constexpr as of C++26 20 | } 21 | } 22 | 23 | int main() 24 | { 25 | constexpr int a = sqrt(100); // Uses slow version 26 | int b = sqrt(1'000'000'000); // Uses fast version 27 | 28 | std::println("a: {} - b: {}", a, b); 29 | } 30 | -------------------------------------------------------------------------------- /Examples/Chapter 09/Ex9_02.cpp: -------------------------------------------------------------------------------- 1 | // Working with std::expected<> 2 | import std; 3 | 4 | enum class Error { WhoopsADaisy, DisasterStruck, OhMy }; 5 | std::expected concoctSomeWhatchamacallit(int wobble) 6 | { 7 | if (wobble < 0) 8 | return std::unexpected{ Error::WhoopsADaisy };/* Not return Error::WhoopsADaisy;! */ 9 | else 10 | return "Some superb doohickey"; 11 | } 12 | 13 | 14 | int main() 15 | { 16 | const auto doohickey = concoctSomeWhatchamacallit(42); 17 | 18 | if (doohickey) 19 | std::println("{}", *doohickey); 20 | else 21 | std::println("An unexpected error occurred (code: {})", static_cast(doohickey.error())); 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Chapter 10/Ex10_03.cpp: -------------------------------------------------------------------------------- 1 | // Using return type deduction with templates 2 | import std; 3 | 4 | // Template for functions to return the larger of two values 5 | // Supports implicit conversion of differently-typed arguments 6 | template 7 | auto larger(const T1& a, const T2& b) 8 | { 9 | return a > b ? a : b; 10 | } 11 | 12 | int main() 13 | { 14 | const int small_int {10}; 15 | std::println("Larger of {} and 9.6 is {}", 16 | small_int, larger(small_int, 9.6)); // deduced return type: double 17 | 18 | const std::string a_string {"A"}; 19 | std::println(R"(Larger of "{}" and "Z" is "{}")", 20 | a_string , larger(a_string, "Z")); // deduced return type: std::string 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Examples/Chapter 10/Ex10_04.cpp: -------------------------------------------------------------------------------- 1 | // constexpr if 2 | import std; 3 | 4 | template 5 | decltype(auto) larger(const T& a, const T& b) 6 | { 7 | if constexpr (std::is_pointer_v) 8 | return *a > *b ? a : b; // Only compiled if T is a pointer type 9 | else 10 | return a > b ? a : b; // Only compiled if T is not a pointer type 11 | } 12 | 13 | int main() 14 | { 15 | const int big_int {17011983}, small_int {10}; 16 | std::println("Larger of {} and {} is {}", 17 | big_int, small_int, larger(big_int, small_int)); 18 | std::println("Larger of {} and {} is {}", 19 | big_int, small_int, *larger(&big_int, &small_int)); 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_01/Ex11_01.cpp: -------------------------------------------------------------------------------- 1 | // Consuming your own module 2 | import std; 3 | import math; 4 | 5 | int main() 6 | { 7 | std::println("Lambda squared: {}", square(lambda)); 8 | 9 | int number; 10 | std::print("\nPlease enter an odd number: "); 11 | std::cin >> number; 12 | std::println(""); 13 | 14 | // if (isOdd(number)) /* Error: identifier not found: 'isOdd' */ 15 | // std::println("Well done!"); 16 | 17 | switch (getOddity(number)) 18 | { 19 | using enum Oddity; 20 | case Odd: 21 | std::println("Well done! And remember: you have to be odd to be number one!"); 22 | break; 23 | case Even: 24 | std::println("Odd, {} appears to be even?", number); 25 | break; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_01/math.cppm: -------------------------------------------------------------------------------- 1 | export module math; 2 | 3 | export auto square(const auto& x) { return x * x; } // An abbreviated function template 4 | 5 | export const double lambda{ 1.303577269034296391257 }; // Conway's constant 6 | 7 | export enum class Oddity { Even, Odd }; 8 | bool isOdd(int x) { return x % 2 != 0; } // Module-local function (not exported) 9 | export auto getOddity(int x) { return isOdd(x) ? Oddity::Odd : Oddity::Even; } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_01A/Ex11_01A.cpp: -------------------------------------------------------------------------------- 1 | // Consuming your own module 2 | import std; 3 | import math; 4 | 5 | int main() 6 | { 7 | std::println("Lambda squared: {}", square(lambda)); 8 | 9 | int number; 10 | std::print("\nPlease enter an odd number: "); 11 | std::cin >> number; 12 | std::println(""); 13 | 14 | // if (isOdd(number)) /* Error: identifier not found: 'isOdd' */ 15 | // std::println("Well done!"); 16 | 17 | switch (getOddity(number)) 18 | { 19 | using enum Oddity; 20 | case Odd: 21 | std::println("Well done! And remember: you have to be odd to be number one!"); 22 | break; 23 | case Even: 24 | std::println("Odd, {} seems to be even?", number); 25 | break; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_01A/math.cppm: -------------------------------------------------------------------------------- 1 | export module math; 2 | 3 | bool isOdd(int x) { return x % 2 != 0; } // Module-local function (not exported) 4 | 5 | export 6 | { 7 | auto square(const auto& x) { return x * x; } 8 | 9 | const double lambda{ 1.303577269034296391257 }; // Conway's constant 10 | 11 | enum class Oddity { Even, Odd }; 12 | auto getOddity(int x) { return isOdd(x) ? Oddity::Odd : Oddity::Even; } 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_01B/Ex11_01B.cpp: -------------------------------------------------------------------------------- 1 | // Consuming your own module 2 | import std; 3 | import math; 4 | 5 | int main() 6 | { 7 | std::println("Lambda squared: {}", square(lambda)); 8 | 9 | int number; 10 | std::print("\nPlease enter an odd number: "); 11 | std::cin >> number; 12 | std::println(""); 13 | 14 | // if (isOdd(number)) /* Error: identifier not found: 'isOdd' */ 15 | // std::println("Well done!"); 16 | 17 | switch (getOddity(number)) 18 | { 19 | using enum Oddity; 20 | case Odd: 21 | std::println("Well done! And remember: you have to be odd to be number one!"); 22 | break; 23 | case Even: 24 | std::println("Odd, {} seems to be even?", number); 25 | break; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_01B/math.cppm: -------------------------------------------------------------------------------- 1 | export module math; 2 | 3 | export 4 | { 5 | auto square(const auto& x); 6 | 7 | const double lambda{ 1.303577269034296391257 }; // Conway's constant 8 | 9 | enum class Oddity { Even, Odd }; 10 | auto getOddity(int x); 11 | } 12 | 13 | // The implementation of the module's functions (+ local helpers) 14 | auto square(const auto& x) { return x * x; } 15 | 16 | bool isOdd(int x) { return x % 2 != 0; } 17 | auto getOddity(int x) { return isOdd(x) ? Oddity::Odd : Oddity::Even; } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_02/Ex11_02.cpp: -------------------------------------------------------------------------------- 1 | // Defining functions in module implementation files 2 | import std; 3 | import roman; 4 | 5 | int main() 6 | { 7 | std::println("1234 in Roman numerals is {}", to_roman(1234)); 8 | std::println("MMXXIII in Arabic numerals is {}", from_roman("MMXXIII")); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_02/roman.cppm: -------------------------------------------------------------------------------- 1 | // Interface file for a Roman numerals module 2 | export module roman; 3 | import std; 4 | 5 | export std::string to_roman(unsigned int i); 6 | export unsigned int from_roman(std::string_view roman); -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_02/to_roman.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the to_roman() function 2 | module roman; 3 | 4 | std::string to_roman(unsigned int i) 5 | { 6 | if (i > 3999) return {}; // 3999, or MMMCMXCIX, is the largest standard Roman numeral 7 | static const std::string ms[]{ "","M","MM","MMM" }; 8 | static const std::string cds[]{ "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" }; 9 | static const std::string xls[]{ "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC" }; 10 | static const std::string ivs[]{ "","I","II","III","IV","V","VI","VII","VIII","IX" }; 11 | return ms[i / 1000] + cds[(i % 1000) / 100] + xls[(i % 100) / 10] + ivs[i % 10]; 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_03/roman.cppm: -------------------------------------------------------------------------------- 1 | // Interface file for a Roman numerals module 2 | export module roman; 3 | import std; 4 | 5 | export std::string to_roman(unsigned int i); 6 | export unsigned int from_roman(std::string_view roman); -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_03/to_roman.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the to_roman() function 2 | module roman; 3 | 4 | std::string to_roman(unsigned int i) 5 | { 6 | if (i > 3999) return {}; // 3999, or MMMCMXCIX, is the largest standard Roman numeral 7 | static const std::string ms[]{ "","M","MM","MMM" }; 8 | static const std::string cds[]{ "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" }; 9 | static const std::string xls[]{ "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC" }; 10 | static const std::string ivs[]{ "","I","II","III","IV","V","VI","VII","VIII","IX" }; 11 | return ms[i / 1000] + cds[(i % 1000) / 100] + xls[(i % 100) / 10] + ivs[i % 10]; 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04A/Ex11_04A.cpp: -------------------------------------------------------------------------------- 1 | // Simulating submodules 2 | import std; 3 | import roman; 4 | 5 | int main() 6 | { 7 | std::println("1234 in Roman numerals is {}", to_roman(1234)); 8 | std::println("MMXX in Arabic numerals is {}", from_roman("MMXXIII")); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04A/from_roman.cppm: -------------------------------------------------------------------------------- 1 | // Module interface file of the roman.from module 2 | export module roman.from; 3 | import std; 4 | export unsigned int from_roman(std::string_view roman); 5 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04A/roman.cppm: -------------------------------------------------------------------------------- 1 | // Module interface file of the roman module 2 | export module roman; 3 | export import roman.from; // Not: 'export import .from;' (cf. partitions later) 4 | export import roman.to; 5 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04A/to_roman.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the to_roman() function 2 | module roman.to; 3 | 4 | std::string to_roman(unsigned int i) 5 | { 6 | if (i > 3999) return {}; // 3999, or MMMCMXCIX, is the largest standard Roman numeral 7 | static const std::string ms[]{ "","M","MM","MMM" }; 8 | static const std::string cds[]{ "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" }; 9 | static const std::string xls[]{ "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC" }; 10 | static const std::string ivs[]{ "","I","II","III","IV","V","VI","VII","VIII","IX" }; 11 | return ms[i / 1000] + cds[(i % 1000) / 100] + xls[(i % 100) / 10] + ivs[i % 10]; 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04A/to_roman.cppm: -------------------------------------------------------------------------------- 1 | // Module interface file of the roman.to module 2 | export module roman.to; 3 | import std; 4 | export std::string to_roman(unsigned int i); 5 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04B/Ex11_04B.cpp: -------------------------------------------------------------------------------- 1 | // Module implementation partitions 2 | import std; 3 | import roman; 4 | 5 | int main() 6 | { 7 | std::println("1234 in Roman numerals is {}", to_roman(1234)); 8 | std::println("MMXX in Arabic numerals is {}", from_roman("MMXXIII")); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04B/from_roman.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the from_roman() function 2 | module roman; 3 | import :internals; 4 | 5 | unsigned int from_roman(std::string_view roman) 6 | { 7 | unsigned int result{}; 8 | for (std::size_t i{}, n{ roman.length() }; i < n; ++i) 9 | { 10 | const auto j{ from_roman(roman[i]) }; // Integer value of the i'th roman digit 11 | // Look at the next digit (if there is one) to know whether to add or subtract j 12 | if (i + 1 == n || j >= from_roman(roman[i + 1])) result += j; else result -= j; 13 | } 14 | return result; 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04B/roman-internals.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the internal from_roman() function 2 | module roman:internals; 3 | 4 | unsigned int from_roman(char c) 5 | { 6 | switch (c) 7 | { 8 | case 'I': return 1; case 'V': return 5; case 'X': return 10; 9 | case 'L': return 50; case 'C': return 100; case 'D': return 500; 10 | case 'M': return 1000; default: return 0; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04B/roman.cppm: -------------------------------------------------------------------------------- 1 | // Interface file for a Roman numerals module 2 | export module roman; 3 | import std; 4 | 5 | export std::string to_roman(unsigned int i); 6 | export unsigned int from_roman(std::string_view roman); -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_04B/to_roman.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the to_roman() function 2 | module roman; 3 | 4 | std::string to_roman(unsigned int i) 5 | { 6 | if (i > 3999) return {}; // 3999, or MMMCMXCIX, is the largest standard Roman numeral 7 | static const std::string ms[]{ "","M","MM","MMM" }; 8 | static const std::string cds[]{ "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" }; 9 | static const std::string xls[]{ "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC" }; 10 | static const std::string ivs[]{ "","I","II","III","IV","V","VI","VII","VIII","IX" }; 11 | return ms[i / 1000] + cds[(i % 1000) / 100] + xls[(i % 100) / 10] + ivs[i % 10]; 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_05/Ex11_05.cpp: -------------------------------------------------------------------------------- 1 | // Creating module interface partitions 2 | import std; 3 | import roman; 4 | 5 | int main() 6 | { 7 | std::println("1234 in Roman numerals is {}", to_roman(1234)); 8 | std::println("MMXX in Arabic numerals is {}", from_roman("MMXXIII")); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_05/from_roman.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the from_roman() function 2 | module roman; 3 | import :internals; 4 | 5 | unsigned int from_roman(std::string_view roman) 6 | { 7 | unsigned int result{}; 8 | for (std::size_t i{}, n{ roman.length() }; i < n; ++i) 9 | { 10 | const auto j{ from_roman(roman[i]) }; // Integer value of the i'th roman digit 11 | // Look at the next digit (if there is one) to know whether to add or subtract j 12 | if (i + 1 == n || j >= from_roman(roman[i + 1])) result += j; else result -= j; 13 | } 14 | return result; 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_05/roman-from.cppm: -------------------------------------------------------------------------------- 1 | // Module interface file for the from partition of the roman module 2 | export module roman:from; 3 | import std; 4 | 5 | export unsigned int from_roman(std::string_view roman); -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_05/roman-internals.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of the internal from_roman() function 2 | module roman:internals; 3 | 4 | unsigned int from_roman(char c) 5 | { 6 | switch (c) 7 | { 8 | case 'I': return 1; case 'V': return 5; case 'X': return 10; 9 | case 'L': return 50; case 'C': return 100; case 'D': return 500; 10 | case 'M': return 1000; default: return 0; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_05/roman-to.cppm: -------------------------------------------------------------------------------- 1 | // Module interface file for the to partition of the roman module 2 | export module roman:to; 3 | import std; 4 | 5 | export std::string to_roman(unsigned int i) 6 | { 7 | if (i > 3999) return {}; // 3999, or MMMCMXCIX, is the largest standard Roman numeral 8 | static const std::string ms[]{ "","M","MM","MMM" }; 9 | static const std::string cds[]{ "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" }; 10 | static const std::string xls[]{ "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC" }; 11 | static const std::string ivs[]{ "","I","II","III","IV","V","VI","VII","VIII","IX" }; 12 | return ms[i / 1000] + cds[(i % 1000) / 100] + xls[(i % 100) / 10] + ivs[i % 10]; 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_05/roman.cppm: -------------------------------------------------------------------------------- 1 | // Primary module interface file for the roman module 2 | export module roman; 3 | 4 | export import :to; // Not: 'export import roman:to;' 5 | export import :from; // Not: 'export import roman:from;' 6 | // export import :internals; /* Error: only interface partitions can be exported */ 7 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_06/Ex11_06.cpp: -------------------------------------------------------------------------------- 1 | import std; 2 | 3 | namespace math 4 | { 5 | const double sqrt2 { 1.414213562373095 }; // the square root of 2 6 | auto square(const auto& x) { return x * x; } 7 | auto pow4(const auto& x) { return square(square(x)); } 8 | } 9 | 10 | int main() 11 | { 12 | std::println("math::sqrt2 has the value {}", math::sqrt2); 13 | std::println("Squared that number equals {}", math::square(math::sqrt2)); 14 | std::println("This should be 0: {}", math::sqrt2 - std::numbers::sqrt2); 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_06A/Ex11_06A.cpp: -------------------------------------------------------------------------------- 1 | // Defining and using a namespace 2 | import std; 3 | import squaring; 4 | 5 | int main() 6 | { 7 | std::println("math::sqrt2 has the value {}", math::sqrt2); 8 | std::println("Squared that number equals {}", math::square(math::sqrt2)); 9 | std::println("This should be 0: {}", math::sqrt2 - std::numbers::sqrt2); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_06A/squaring.cppm: -------------------------------------------------------------------------------- 1 | export module squaring; 2 | 3 | namespace math 4 | { 5 | export const double sqrt2{ 1.414213562373095 }; // the square root of 2 6 | export auto square(const auto& x) { return x * x; } 7 | export auto pow4(const auto& x) { return square(square(x)); } 8 | } -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_06B/Ex11_06B.cpp: -------------------------------------------------------------------------------- 1 | // Defining and using a namespace 2 | import std; 3 | import squaring; 4 | 5 | int main() 6 | { 7 | std::println("math::sqrt2 has the value {}", math::sqrt2); 8 | std::println("Squared that number equals {}", math::square(math::sqrt2)); 9 | std::println("This should be 0: {}", math::sqrt2 - std::numbers::sqrt2); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_06B/squaring.cppm: -------------------------------------------------------------------------------- 1 | export module squaring; 2 | 3 | export namespace math // Exports all nested declarations at once 4 | { 5 | const double sqrt2{ 1.414213562373095 }; // the square root of 2 6 | auto square(const auto& x) { return x * x; } 7 | auto pow4(const auto& x) { return square(square(x)); } 8 | } -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_07/Ex11_07.cpp: -------------------------------------------------------------------------------- 1 | // Separating declarations and definitions of functions 2 | // declared in a namespace. 3 | import std; 4 | import math; 5 | 6 | int main() 7 | { 8 | const double values[]{ 10, 2, 1, 8, 3, 7, 4, 5, 6, 9 }; 9 | std::println("Arithmetic mean: {}", math::averages::arithmetic_mean(values)); 10 | std::println("Geometric mean: {}", math::averages::geometric_mean(values)); 11 | std::println("Root mean square: {}", math::averages::rms(values)); 12 | std::println("Median: {}", math::averages::median(values)); 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_07/math.cppm: -------------------------------------------------------------------------------- 1 | export module math; 2 | 3 | import std; 4 | 5 | export namespace math 6 | { 7 | auto square(const auto& x) { return x * x; }; 8 | 9 | namespace averages 10 | { 11 | double arithmetic_mean(std::span data); 12 | double geometric_mean(std::span data); 13 | double rms(std::span data); 14 | double median(std::span data); 15 | } 16 | } -------------------------------------------------------------------------------- /Examples/Chapter 11/Ex11_08/squaring.cppm: -------------------------------------------------------------------------------- 1 | export module squaring; 2 | import std; 3 | 4 | /* Re-export two existing entities from the math namespace using using declarations */ 5 | export namespace math // Exports all nested declarations at once 6 | { 7 | using std::numbers::sqrt2; 8 | using std::sqrt; // Never 'using std::sqrt();' or 'using std::sqrt(double);'! 9 | auto square(const auto& x) { return x * x; } 10 | auto pow4(const auto& x) { return square(square(x)); } 11 | } 12 | 13 | /* Export all names from a namespace from the math namespace using a using directive */ 14 | //namespace math 15 | //{ 16 | // export using namespace std::numbers; 17 | //} -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_07/Ex12_07.cpp: -------------------------------------------------------------------------------- 1 | // Exporting a class from a module 2 | import std; 3 | import box; // For use of the Box class 4 | 5 | int main() 6 | { 7 | Box myBox{ 6.0, 6.0, 18.5 }; // Create a box 8 | std::println("My box's volume is {}", myBox.volume()); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_07A/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | import std; 3 | 4 | // Class to represent a box 5 | export class Box 6 | { 7 | public: 8 | Box() = default; 9 | Box(double length, double width, double height) 10 | : m_length{ length }, m_width{ width }, m_height{ height } 11 | { 12 | std::println("Box constructor called."); 13 | } 14 | 15 | // Function to calculate the volume of a box 16 | double volume() { return m_length * m_width * m_height; } 17 | 18 | private: 19 | double m_length{ 1.0 }; 20 | double m_width{ 1.0 }; 21 | double m_height{ 1.0 }; 22 | }; 23 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_07A/Ex12_07A.cpp: -------------------------------------------------------------------------------- 1 | // Defining classes with in-class member definitions. 2 | 3 | import std; 4 | import box; // For use of the Box class 5 | 6 | int main() 7 | { 8 | Box myBox{ 6.0, 6.0, 18.5 }; // Create a box 9 | std::println("My box's volume is {}", myBox.volume()); 10 | } -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_07B/Box.cpp: -------------------------------------------------------------------------------- 1 | module box; 2 | import std; 3 | 4 | // Constructor definition 5 | Box::Box(double length, double width, double height) 6 | : m_length{ length }, m_width{ width }, m_height{ height } 7 | { 8 | std::println("Box constructor called."); 9 | } 10 | 11 | // Member function definition 12 | double Box::volume() 13 | { 14 | return m_length * m_width * m_height; 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_07B/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | // Class to represent a box 4 | export class Box 5 | { 6 | public: 7 | Box() = default; 8 | Box(double length, double width, double height); 9 | 10 | double volume(); // Function to calculate the volume of a box 11 | 12 | private: 13 | double m_length{ 1.0 }; 14 | double m_width{ 1.0 }; 15 | double m_height{ 1.0 }; 16 | }; 17 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_07B/Ex12_07B.cpp: -------------------------------------------------------------------------------- 1 | // Defining class members in a module implementation file 2 | 3 | import std; 4 | import box; // For use of the Box class 5 | 6 | int main() 7 | { 8 | Box myBox{ 6.0, 6.0, 18.5 }; // Create a box 9 | std::println("My box's volume is {}", myBox.volume()); 10 | } -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_08/Box.cpp: -------------------------------------------------------------------------------- 1 | module box; 2 | 3 | import std; 4 | 5 | // Constructor definition 6 | Box::Box(double length, double width, double height) 7 | : m_length{ length }, m_width{ width }, m_height{ height } 8 | { 9 | std::println("Box constructor called."); 10 | } 11 | 12 | // Member function definition 13 | double Box::volume() 14 | { 15 | return m_length * m_width * m_height; 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_08/Ex12_08.cpp: -------------------------------------------------------------------------------- 1 | // Accessing private members through getters and setters 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | Box myBox {3.0, 4.0, 5.0}; 8 | std::println("myBox dimensions are {} by {} by {}", 9 | myBox.getLength(), myBox.getWidth(), myBox.getHeight()); 10 | 11 | myBox.setLength(-20.0); // ignored! 12 | myBox.setWidth(40.0); 13 | myBox.setHeight(10.0); 14 | std::println("myBox dimensions are now {} by {} by {}", 15 | myBox.getLength(), // 3 (unchanged) 16 | myBox.getWidth(), // by 40 17 | myBox.getHeight() // by 10 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_09/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | // Constructors 7 | Box() = default; 8 | Box(double length, double width, double height); 9 | 10 | double volume(); // Function to calculate the volume of a box 11 | 12 | // Inspector functions 13 | double getLength() { return m_length; } 14 | double getWidth() { return m_width; } 15 | double getHeight() { return m_height; } 16 | 17 | // Mutator functions 18 | Box& setLength(double length); 19 | Box& setWidth(double width); 20 | Box& setHeight(double height); 21 | 22 | private: 23 | double m_length{1.0}; 24 | double m_width {1.0}; 25 | double m_height{1.0}; 26 | }; 27 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_09/Ex12_09.cpp: -------------------------------------------------------------------------------- 1 | // Accessing private members through getters and setters (method chaining variant) 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | Box myBox {3.0, 4.0, 5.0}; 8 | std::println("myBox dimensions are {} by {} by {}", 9 | myBox.getLength(), myBox.getWidth(), myBox.getHeight()); 10 | 11 | myBox.setLength(-20.0).setWidth(40.0).setHeight(10.0); // Set all dimensions of myBox 12 | 13 | std::println("myBox dimensions are now {} by {} by {}", 14 | myBox.getLength(), // 3 (unchanged) 15 | myBox.getWidth(), // by 40 16 | myBox.getHeight() // by 10 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_10/Box.cpp: -------------------------------------------------------------------------------- 1 | module box; 2 | 3 | import std; 4 | 5 | // Constructor definition 6 | Box::Box(double length, double width, double height) 7 | : m_length{ length }, m_width{ width }, m_height{ height } 8 | { 9 | std::println("Box constructor called."); 10 | } 11 | 12 | // Const member function definition 13 | double Box::volume() const 14 | { 15 | return m_length * m_width * m_height; 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_11/Box.cpp: -------------------------------------------------------------------------------- 1 | module box; 2 | import std; 3 | 4 | // Constructor definition 5 | Box::Box(double length, double width, double height) 6 | : m_length{ length }, m_width{ width }, m_height{ height } 7 | { 8 | std::println("Box constructor called."); 9 | } 10 | 11 | // Const member function definition 12 | double Box::volume() const 13 | { 14 | return m_length * m_width * m_height; 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_11/Ex12_11.cpp: -------------------------------------------------------------------------------- 1 | // Overloading on const 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | const Box constBox{ 1, 2, 3 }; 8 | // constBox.length() = 2; // Does not compile: good! 9 | std::println("{}", constBox.length()); 10 | 11 | Box nonConstBox{ 3, 2, 1 }; 12 | nonConstBox.length() *= 2; 13 | std::println("{}", nonConstBox.length()); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_12/Box.cpp: -------------------------------------------------------------------------------- 1 | module box; 2 | 3 | import std; 4 | 5 | // Constructor definition 6 | Box::Box(double length, double width, double height) 7 | : m_length{ length }, m_width{ width }, m_height{ height } 8 | { 9 | std::println("Box constructor called."); 10 | } 11 | 12 | // Const member function definition 13 | double Box::volume() const 14 | { 15 | return m_length * m_width * m_height; 16 | } 17 | 18 | // Modify mutable member variable from a const member function 19 | void Box::printVolume() const 20 | { 21 | // Count how many times printVolume() is called using a mutable member in a const function 22 | std::println("The volume of this box is {}", volume()); 23 | std::println("printVolume() has been called {} time(s)", ++m_count); 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_12/Ex12_12.cpp: -------------------------------------------------------------------------------- 1 | // Const objects and const member functions 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | const Box myBox {3.0, 4.0, 5.0}; 8 | std::println("myBox dimensions are {} by {} by {}", 9 | myBox.getLength(), myBox.getWidth(), myBox.getHeight()); 10 | 11 | myBox.printVolume(); 12 | myBox.printVolume(); 13 | myBox.printVolume(); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_13/Box.cpp: -------------------------------------------------------------------------------- 1 | module box; 2 | 3 | import std; 4 | 5 | // Constructor definition 6 | Box::Box(double length, double width, double height) 7 | : m_length{ length }, m_width{ width }, m_height{ height } 8 | { 9 | std::println("Box constructor called."); 10 | } 11 | 12 | // Const member function definition 13 | double Box::volume() const 14 | { 15 | return m_length * m_width * m_height; 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_13/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() : Box{ 1.0, 1.0, 1.0} {} // A delegating default constructor 7 | Box(double length, double width, double height); 8 | 9 | double volume() const; // Function to calculate the volume of a box 10 | 11 | friend double surfaceArea(const Box& box); // Friend function for the surface area 12 | 13 | private: 14 | double m_length, m_width, m_height; 15 | }; 16 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_14/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | /* Constructors */ 7 | Box(double length, double width, double height); 8 | Box(double side); // Constructor for a cube 9 | Box(); // Default constructor 10 | Box(const Box& box); // Copy constructor 11 | 12 | double volume() const { return m_length * m_width * m_height; }; 13 | 14 | private: 15 | double m_length {1.0}; 16 | double m_width {1.0}; 17 | double m_height {1.0}; 18 | }; 19 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_14/Ex12_14.cpp: -------------------------------------------------------------------------------- 1 | // Creating an array of objects 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | const Box box1 {2.0, 3.0, 4.0}; // An arbitrary box 8 | Box box2 {5.0}; // A box that is a cube 9 | std::println("box1 volume = {}", box1.volume()); 10 | std::println("box2 volume = {}", box2.volume()); 11 | Box box3 {box2}; 12 | std::println("box3 volume = {}", box3.volume()); // Volume = 125 13 | 14 | std::println(""); 15 | 16 | Box boxes[6] {box1, box2, box3, Box {2.0}}; 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_15/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | import std; 4 | 5 | export class Box 6 | { 7 | public: 8 | Box(); // Default constructor 9 | Box(double side); // Constructor for a cube 10 | Box(const Box& box); // Copy constructor 11 | Box(double length, double width, double height); 12 | 13 | double volume() const { return m_length * m_width * m_height; } 14 | 15 | std::size_t getObjectCount() const { return s_object_count; } 16 | 17 | private: 18 | double m_length {1.0}; 19 | double m_width {1.0}; 20 | double m_height {1.0}; 21 | static inline std::size_t s_object_count {}; // Count of objects ever created 22 | }; 23 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_15/Ex12_15.cpp: -------------------------------------------------------------------------------- 1 | // Using a static member variable 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | const Box box1{ 2.0, 3.0, 4.0 }; // An arbitrary box 8 | Box box2{5.0}; // A cube 9 | std::println("box1 volume = {}", box1.volume()); 10 | std::println("box2 volume = {}", box2.volume()); 11 | Box box3 {box2}; 12 | std::println("box3 volume = {}", box3.volume()); // Volume = 125 13 | 14 | std::println(""); 15 | 16 | Box boxes[6] { box1, box2, box3, Box{2.0} }; 17 | 18 | std::println("\nThere are now {} Box objects.", box1.getObjectCount()); 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_16/CylindricalBox.cpp: -------------------------------------------------------------------------------- 1 | module cylindrical; 2 | 3 | import std; 4 | 5 | CylindricalBox::CylindricalBox(float radius, float height, std::string_view material) 6 | : m_radius{ radius } 7 | , m_height{ height } 8 | , m_material{ material } 9 | { 10 | std::print("Box constructed consisting of {}", material); 11 | if (material == s_default_material) 12 | { 13 | std::print(" (the default material!)"); 14 | } 15 | std::println(""); 16 | } 17 | 18 | float CylindricalBox::volume() const 19 | { 20 | return PI * m_radius * m_radius * m_height; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_16/CylindricalBox.cppm: -------------------------------------------------------------------------------- 1 | export module cylindrical; 2 | 3 | import std; 4 | 5 | export class CylindricalBox 6 | { 7 | public: 8 | static inline const float s_max_radius { 35.0f }; 9 | static inline const float s_max_height { 60.0f }; 10 | static inline const std::string_view s_default_material { "paperboard" }; 11 | 12 | CylindricalBox(float radius, float height, 13 | std::string_view material = s_default_material); 14 | float volume() const; 15 | 16 | private: 17 | // The value of PI used by CylindricalBox's volume() function 18 | static inline const float PI { 3.141592f }; 19 | 20 | float m_radius; 21 | float m_height; 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_16/Ex12_16.cpp: -------------------------------------------------------------------------------- 1 | // Defining and using static constants 2 | import std; 3 | import cylindrical; 4 | 5 | int main() 6 | { 7 | CylindricalBox bigBox{ 1.23f, 8 | CylindricalBox::s_max_height, CylindricalBox::s_default_material }; 9 | std::println("The volume of bigBox is {}", bigBox.volume()); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_17/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | import std; 4 | 5 | export class Box 6 | { 7 | public: 8 | Box(); // Default constructor 9 | Box(double side); // Constructor for a cube 10 | Box(const Box& box); // Copy constructor 11 | Box(double length, double width, double height); 12 | ~Box(); // Destructor 13 | 14 | double volume() const { return m_length * m_width * m_height; } 15 | 16 | static std::size_t getObjectCount() { return s_object_count; } 17 | 18 | private: 19 | double m_length {1.0}; 20 | double m_width {1.0}; 21 | double m_height {1.0}; 22 | static inline std::size_t s_object_count {}; // Count of objects ever created 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_18/Package.cpp: -------------------------------------------------------------------------------- 1 | module truckload:package; 2 | 3 | import :shared_box; 4 | 5 | class Package 6 | { 7 | public: 8 | Package(SharedBox box) : m_box{box}, m_next{nullptr} {} // Constructor 9 | ~Package() { delete m_next; } // Destructor 10 | 11 | // Retrieve the Box pointer 12 | SharedBox getBox() const { return m_box; } 13 | 14 | // Retrieve or update the pointer to the next Package 15 | Package* getNext() { return m_next; } 16 | void setNext(Package* package) { m_next = package; } 17 | 18 | private: 19 | SharedBox m_box; // Pointer to the Box object contained in this Package 20 | Package* m_next; // Pointer to the next Package in the list 21 | }; 22 | -------------------------------------------------------------------------------- /Examples/Chapter 12/Ex12_18/SharedBox.cppm: -------------------------------------------------------------------------------- 1 | // Minor interface partition exporting the SharedBox type alias 2 | export module truckload:shared_box; 3 | import std; 4 | import box; 5 | export using SharedBox = std::shared_ptr; 6 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_01/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | // Constructors 7 | Box() = default; 8 | Box(double l, double w, double h) : m_length{l}, m_width{w}, m_height{h} {} 9 | 10 | double volume() const { return m_length * m_width * m_height; } 11 | 12 | // Accessors 13 | double getLength() const { return m_length; } 14 | double getWidth() const { return m_width; } 15 | double getHeight() const { return m_height; } 16 | 17 | bool operator<(const Box& aBox) const // Less-than operator 18 | { return volume() < aBox.volume(); } 19 | 20 | private: 21 | double m_length {1.0}; 22 | double m_width {1.0}; 23 | double m_height {1.0}; 24 | }; 25 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_01/Ex13_01.cpp: -------------------------------------------------------------------------------- 1 | // Implementing a less-than operator 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | std::vector boxes {Box {2.0, 2.0, 3.0}, Box {1.0, 3.0, 2.0}, 8 | Box {1.0, 2.0, 1.0}, Box {2.0, 3.0, 3.0}}; 9 | Box smallBox {boxes[0]}; 10 | for (const auto& box : boxes) 11 | { 12 | if (box < smallBox) smallBox = box; 13 | } 14 | 15 | std::println("The smallest box has dimensions {} x {} x {}", 16 | smallBox.getLength(), smallBox.getWidth(), smallBox.getHeight()); 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_02/Ex13_02.cpp: -------------------------------------------------------------------------------- 1 | // Using the overloaded 'less-than' operators for Box objects 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | std::vector boxes {Box {2.0, 2.0, 3.0}, Box {1.0, 3.0, 2.0}, 8 | Box {1.0, 2.0, 1.0}, Box {2.0, 3.0, 3.0}}; 9 | const double minVolume{6.0}; 10 | 11 | std::println("Objects with volumes less than {} are:", minVolume); 12 | for (const auto& box : boxes) 13 | if (box < minVolume) std::println("{}", to_string(box)); 14 | 15 | std::println("Objects with volumes greater than {} are:", minVolume); 16 | for (const auto& box : boxes) 17 | if (minVolume < box) std::println("{}", to_string(box)); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_07/Ex13_07.cpp: -------------------------------------------------------------------------------- 1 | // Implicit conversions reduce the number of operator functions 2 | import std; 3 | import integer; 4 | 5 | int main() 6 | { 7 | const Integer i{1}; 8 | const Integer j{2}; 9 | const auto result = (i * 2 + 4 / j - 1) % j; 10 | std::println("{}", result.getValue()); 11 | } 12 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_08/Ex13_08.cpp: -------------------------------------------------------------------------------- 1 | // Overloading a unary "rotate" operator 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | Box someBox{ 1, 2, 3 }; 8 | std::println("{}", to_string( ~someBox )); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_09/Ex13_09.cpp: -------------------------------------------------------------------------------- 1 | // Overloading pre- and postfix increment and decrement operators 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | Box theBox{ 3.0, 1.0, 3.0 }; 8 | 9 | std::println("Our test Box is {}", to_string(theBox)); 10 | 11 | std::println("Postfix increment evaluates to the original object: {}", 12 | to_string(theBox++)); 13 | std::println("After postfix increment: {}", to_string(theBox)); 14 | 15 | std::println("Prefix decrement evaluates to the decremented object: {}", 16 | to_string(--theBox)); 17 | std::println("After prefix decrement: {}", to_string(theBox)); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_12/Ex13_12.cpp: -------------------------------------------------------------------------------- 1 | // Defining a copy assignment operator 2 | import message; 3 | import std; 4 | 5 | int main() 6 | { 7 | Message beware{ "Careful" }; 8 | Message warning; 9 | 10 | warning = beware; // Call assignment operator 11 | 12 | std::println("After assignment beware is: {}", beware.getText()); 13 | std::println("After assignment warning is: {}", warning.getText()); 14 | } -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_12/Message.cpp: -------------------------------------------------------------------------------- 1 | module message; 2 | 3 | Message& Message::operator=(const Message& message) 4 | { 5 | if (&message != this) 6 | { 7 | delete[] m_text; // Delete the previous char array 8 | m_text = new char[std::strlen(message.m_text) + 1]; // Replace it with a new array 9 | std::strcpy(m_text, message.m_text); // Copy the text (mind the order!) 10 | } 11 | return *this; // Return the left operand 12 | } -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_12/Message.cppm: -------------------------------------------------------------------------------- 1 | export module message; 2 | import std; 3 | 4 | export class Message 5 | { 6 | public: 7 | explicit Message(const char* text = "") 8 | : m_text(new char[std::strlen(text) + 1]) // Caution: include the null character! 9 | { 10 | std::strcpy(m_text, text); // Mind the order: strcpy(destination, source)! 11 | } 12 | ~Message() { delete[] m_text; } 13 | 14 | Message& operator=(const Message& message); // Assignment operator 15 | 16 | const char* getText() const { return m_text; } 17 | 18 | private: 19 | char* m_text; 20 | }; 21 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_12A/Ex13_12A.cpp: -------------------------------------------------------------------------------- 1 | // Always define both copy members together 2 | // (see also 'Rule of Five' in Chapter 18!) 3 | import message; 4 | import std; 5 | 6 | int main() 7 | { 8 | Message beware{ "Careful" }; 9 | Message warning; 10 | 11 | warning = beware; // Call assignment operator 12 | 13 | Message caution{ warning }; 14 | 15 | std::println("After assignment beware is: {}", beware.getText()); 16 | std::println("After assignment warning is: {}", warning.getText()); 17 | std::println("As a copy of warning, caution is: {}", caution.getText()); 18 | } -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_12A/Message.cpp: -------------------------------------------------------------------------------- 1 | module message; 2 | 3 | Message::Message(const Message& message) 4 | : Message{ message.m_text } // By far easiest and preferred option: forward to existing constructor! 5 | { 6 | } 7 | 8 | Message& Message::operator=(const Message& message) 9 | { 10 | if (&message != this) 11 | { 12 | delete[] m_text; // Delete the previous char array 13 | m_text = new char[std::strlen(message.m_text) + 1]; // Replace it with a new array 14 | std::strcpy(m_text, message.m_text); // Copy the text (mind the order!) 15 | } 16 | return *this; // Return the left operand 17 | } -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_12A/Message.cppm: -------------------------------------------------------------------------------- 1 | export module message; 2 | import std; 3 | 4 | export class Message 5 | { 6 | public: 7 | explicit Message(const char* text = "") 8 | : m_text(new char[std::strlen(text) + 1]) // Caution: include the null character! 9 | { 10 | std::strcpy(m_text, text); // Mind the order: strcpy(destination, source)! 11 | } 12 | ~Message() { delete[] m_text; } 13 | 14 | Message(const Message& message); // Copy constructor 15 | Message& operator=(const Message& message); // Copy assignment operator 16 | 17 | const char* getText() const { return m_text; } 18 | 19 | private: 20 | char* m_text; 21 | }; 22 | -------------------------------------------------------------------------------- /Examples/Chapter 13/Ex13_12B/Message.cpp: -------------------------------------------------------------------------------- 1 | module message; 2 | 3 | import std; 4 | 5 | Message::Message(const Message& message) 6 | : Message{ message.m_text } // By far easiest and preferred option: forward to existing constructor! 7 | { 8 | } 9 | 10 | Message& Message::operator=(const Message& message) 11 | { 12 | // Note: self-assignment test no longer required (or even recommended) 13 | auto copy{ message }; // Copy-... 14 | swap(copy); // ...and-swap! 15 | return *this; // Always return reference to left operand 16 | } 17 | 18 | void Message::swap(Message& other) noexcept 19 | { 20 | std::swap(m_text, other.m_text); 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_01/Box.cppm: -------------------------------------------------------------------------------- 1 | // Box.cppm - defines Box class 2 | export module box; 3 | 4 | export class Box 5 | { 6 | public: 7 | Box() = default; 8 | Box(double length, double width, double height) 9 | : m_length{ length }, m_width{ width }, m_height{ height } 10 | {} 11 | 12 | double volume() const { return m_length * m_width * m_height; } 13 | 14 | // Accessors 15 | double getLength() const { return m_length; } 16 | double getWidth() const { return m_width; } 17 | double getHeight() const { return m_height; } 18 | 19 | private: 20 | double m_length {1.0}; 21 | double m_width {1.0}; 22 | double m_height {1.0}; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_01/Carton.cppm: -------------------------------------------------------------------------------- 1 | // Carton.cppm - defines the Carton class with the Box class as base 2 | export module carton; 3 | 4 | import std; 5 | import box; 6 | 7 | export class Carton : public Box 8 | { 9 | public: 10 | explicit Carton(std::string_view material = "Cardboard") // Constructor 11 | : m_material{material} {} 12 | 13 | private: 14 | std::string m_material; 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_01A/Box.cppm: -------------------------------------------------------------------------------- 1 | // Box.cppm - defines Box class 2 | export module box; 3 | 4 | export class Box 5 | { 6 | public: 7 | Box() = default; 8 | Box(double length, double width, double height) 9 | : m_length{ length }, m_width{ width }, m_height{ height } 10 | {} 11 | 12 | double volume() const { return m_length * m_width * m_height; } 13 | 14 | // Accessors 15 | double getLength() const { return m_length; } 16 | double getWidth() const { return m_width; } 17 | double getHeight() const { return m_height; } 18 | 19 | private: 20 | double m_length {1.0}; 21 | double m_width {1.0}; 22 | double m_height {1.0}; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_01A/Carton.cppm: -------------------------------------------------------------------------------- 1 | // Carton.cppm - defines the Carton class with the Box class as private base 2 | export module carton; 3 | 4 | import std; 5 | import box; 6 | 7 | export class Carton : private Box 8 | { 9 | public: 10 | explicit Carton(std::string_view mat = "Cardboard") : m_material {mat} {} 11 | using Box::volume; // Inherit as public 12 | 13 | private: 14 | std::string m_material; 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_02/Ex14_02.cpp: -------------------------------------------------------------------------------- 1 | // Calling base class constructors in a derived class constructor 2 | import std; 3 | import carton; // For the Carton class 4 | 5 | int main() 6 | { 7 | // Create four Carton objects 8 | Carton carton1; std::println(""); 9 | Carton carton2 {"White-lined chipboard"}; std::println(""); 10 | Carton carton3 {4.0, 5.0, 6.0, "PET"}; std::println(""); 11 | Carton carton4 {2.0, "Folding boxboard"}; std::println(""); 12 | 13 | std::println("carton1 volume is {}", carton1.volume()); 14 | std::println("carton2 volume is {}", carton2.volume()); 15 | std::println("carton3 volume is {}", carton3.volume()); 16 | std::println("carton4 volume is {}", carton4.volume()); 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_03/Ex14_03.cpp: -------------------------------------------------------------------------------- 1 | // Using a derived class copy constructor 2 | import std; 3 | import carton; 4 | 5 | int main() 6 | { 7 | // Declare and initialize a Carton object 8 | Carton carton{ 20.0, 30.0, 40.0, "Expanded polystyrene" }; 9 | std::println(""); 10 | 11 | Carton cartonCopy{ carton }; // Use copy constructor 12 | std::println(""); 13 | 14 | std::println("Volume of carton is {}", carton.volume()); 15 | std::println("Volume of cartonCopy is {}", cartonCopy.volume()); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_04/Ex14_04.cpp: -------------------------------------------------------------------------------- 1 | // Defaulting the default constructor in a derived class (working version) 2 | import std; 3 | import box; // For the Box class 4 | import carton; // For the Carton class 5 | 6 | int main() 7 | { 8 | // Create three Carton objects 9 | Carton carton1; std::println(""); 10 | Carton carton2 {4.0, 5.0, 6.0, "PET"}; std::println(""); 11 | Carton carton3 {2.0, "Folding boxboard"}; std::println(""); 12 | 13 | std::println("carton1 volume is {}", carton1.volume()); 14 | std::println("carton2 volume is {}", carton2.volume()); 15 | std::println("carton3 volume is {}", carton3.volume()); 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_05/Carton.cppm: -------------------------------------------------------------------------------- 1 | // Carton.cppm - defines the Carton class with the Box class as base 2 | export module carton; 3 | 4 | import std; 5 | import box; 6 | 7 | export class Carton : public Box 8 | { 9 | using Box::Box; // Inherit Box class constructors 10 | 11 | public: 12 | Carton() = default; // Required by Visual C++ 13 | Carton(double length, double width, double height, std::string_view mat) 14 | : Box{length, width, height}, m_material{mat} 15 | { std::println("Carton(double, double, double, string_view) called."); } 16 | 17 | private: 18 | std::string m_material {"Cardboard"}; 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_05/Ex14_05.cpp: -------------------------------------------------------------------------------- 1 | // Inheriting constructors 2 | import std; 3 | import carton; // For the Carton class 4 | 5 | int main() 6 | { 7 | Carton cart; // Calls inherited default constructor 8 | Carton cube { 4.0 }; // Calls inherited constructor 9 | Carton copy { cube }; // Calls default copy constructor 10 | Carton carton {1.0, 2.0, 3.0}; // Calls inherited constructor 11 | Carton cerealCarton (50.0, 30.0, 20.0, "Chipboard"); // Calls Carton class constructor 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_06/Ex14_06.cpp: -------------------------------------------------------------------------------- 1 | // Destructors in a class hierarchy 2 | import std; 3 | import carton; // For the Carton class 4 | 5 | int main() 6 | { 7 | Carton carton; 8 | Carton candyCarton{50.0, 30.0, 20.0, "SBB"}; // Solid bleached board 9 | 10 | std::println("carton volume is {}", carton.volume()); 11 | std::println("candyCarton volume is {}", candyCarton.volume()); 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_07/CerealPack.cppm: -------------------------------------------------------------------------------- 1 | // Cerealpack.cppm - Class defining a carton of cereal 2 | export module cereal; 3 | import std; 4 | import carton; 5 | import food; 6 | 7 | export class CerealPack : public Carton, public FoodContainer 8 | { 9 | public: 10 | CerealPack(double length, double width, double height, std::string_view cerealType) 11 | : Carton {length, width, height, "Chipboard"}, FoodContainer {cerealType} 12 | { 13 | std::println("CerealPack constructor"); 14 | FoodContainer::volume = 0.9 * Carton::volume(); // Set food container's volume 15 | } 16 | 17 | ~CerealPack() 18 | { 19 | std::println("CerealPack destructor"); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_07A/CerealPack.cppm: -------------------------------------------------------------------------------- 1 | // Cerealpack.cppm - Class defining a carton of cereal 2 | export module cereal; 3 | import std; 4 | import carton; 5 | import food; 6 | 7 | export class CerealPack : public Carton, public FoodContainer 8 | { 9 | public: 10 | CerealPack(double length, double width, double height, std::string_view cerealType) 11 | : Carton {length, width, height, "Chipboard"}, FoodContainer {cerealType} 12 | { 13 | std::println("CerealPack constructor"); 14 | FoodContainer::volume = 0.9 * Carton::volume(); // Set food container's volume 15 | } 16 | 17 | ~CerealPack() 18 | { 19 | std::println("CerealPack destructor"); 20 | } 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_07A/Ex14_07A.cpp: -------------------------------------------------------------------------------- 1 | // Ex14_07A - Disambiguating ambiguous member inheritance through casting 2 | import std; 3 | import cereal; // For the CerealPack class 4 | 5 | int main() 6 | { 7 | CerealPack cornflakes{ 8.0, 3.0, 10.0, "Cornflakes" }; 8 | 9 | std::println("cornflakes volume is {:.3}", static_cast(cornflakes).volume()); 10 | std::println("cornflakes weight is {:.3}", 11 | static_cast(cornflakes).getWeight()); 12 | 13 | /* 14 | // Alternate solution by explicitly qualifying the base class name (see also Ex14_07) 15 | std::println("cornflakes volume is {:.3}", cornflakes.Carton::volume()); 16 | std::println("cornflakes weight is {:.3}", cornflakes.FoodContainer::getWeight()); 17 | */ 18 | } -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_07B/CerealPack.cppm: -------------------------------------------------------------------------------- 1 | // Cerealpack.cppm - Class defining a carton of cereal 2 | export module cereal; 3 | import std; 4 | import carton; 5 | import food; 6 | 7 | export class CerealPack : public Carton, public FoodContainer 8 | { 9 | public: 10 | CerealPack(double length, double width, double height, std::string_view cerealType) 11 | : Carton {length, width, height, "Chipboard"}, FoodContainer {cerealType} 12 | { 13 | std::println("CerealPack constructor"); 14 | FoodContainer::volume = 0.9 * Carton::volume(); // Set food container's volume 15 | } 16 | 17 | ~CerealPack() 18 | { 19 | std::println("CerealPack destructor"); 20 | } 21 | 22 | using Carton::volume; 23 | using FoodContainer::getWeight; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /Examples/Chapter 14/Ex14_07B/Ex14_07B.cpp: -------------------------------------------------------------------------------- 1 | // Ex14_07B - Disambiguating ambiguous member through 2 | // using declarations in the derived class (CerealPack) 3 | import std; 4 | import cereal; // For the CerealPack class 5 | 6 | int main() 7 | { 8 | CerealPack cornflakes{ 8.0, 3.0, 10.0, "Cornflakes" }; 9 | 10 | std::println("cornflakes volume is {:.3}", cornflakes.volume()); 11 | std::println("cornflakes weight is {:.3}", cornflakes.getWeight()); 12 | } -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_01/Box.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:box; 2 | 3 | import std; 4 | 5 | export class Box 6 | { 7 | public: 8 | Box() : Box{ 1.0, 1.0, 1.0 } {} 9 | Box(double l, double w, double h) : m_length {l}, m_width {w}, m_height {h} {} 10 | 11 | // Function to print the usable volume of a Box object 12 | void printVolume() const 13 | { std::println("Box usable volume is {}", volume()); } 14 | 15 | // Function to calculate the volume of a Box object 16 | double volume() const { return m_length * m_width * m_height; } 17 | 18 | double getLength() const { return m_length; } 19 | double getWidth() const { return m_width; } 20 | double getHeight() const { return m_height; } 21 | 22 | private: 23 | double m_length, m_width, m_height; 24 | }; 25 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_01/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_01/Ex15_01.cpp: -------------------------------------------------------------------------------- 1 | // Behavior of inherited functions in a derived class 2 | import boxes; 3 | 4 | import std; 5 | 6 | int main() 7 | { 8 | Box box {20.0, 30.0, 40.0}; // Create a box 9 | ToughPack hardcase {20.0, 30.0, 40.0}; // Create a tough pack - same size 10 | 11 | box.printVolume(); // Display volume of base box (calls volume() for box) 12 | hardcase.printVolume(); // Display volume of derived box (call volume() for hardcase) 13 | 14 | // std::println("hardcase volume is {}", hardcase.volume()); 15 | // Box* hardcaseBox{ &hardcase }; 16 | // std::println("hardcase volume through a Box* pointer is {}", hardcaseBox->volume()); 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_01/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume() const { return 0.87 * getLength() * getWidth() * getHeight(); } 13 | }; 14 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_02/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; 7 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_02/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_02/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume() const { return 0.87 * getLength() * getWidth() * getHeight(); } 13 | }; 14 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_03/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_03/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const override 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_03/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | protected: 12 | // Function to calculate volume of a ToughPack allowing 13% for packing 13 | double volume() const override { return 0.87 * getLength() * getWidth() * getHeight(); } 14 | }; 15 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_04/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_04/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume(int i = 50) const override 15 | { 16 | std::print("(Carton argument = {}) ", i); 17 | return std::max(getLength() - 0.5, 0.0) 18 | * std::max(getWidth() - 0.5, 0.0) 19 | * std::max(getHeight() - 0.5, 0.0); 20 | } 21 | 22 | private: 23 | std::string m_material; 24 | }; 25 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_04/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume(int i = 500) const override 13 | { 14 | std::print("(ToughPack argument = {}) ", i); 15 | return 0.87 * getLength() * getWidth() * getHeight(); 16 | } 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_05/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_05/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const override 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_05/Ex15_05.cpp: -------------------------------------------------------------------------------- 1 | // Using a reference parameter to call virtual function 2 | import std; 3 | import boxes; 4 | 5 | // Global function to display the volume of a box 6 | void printVolume(const Box& box) 7 | { 8 | std::println("Box usable volume is {}", box.volume()); 9 | } 10 | 11 | int main() 12 | { 13 | Box box {20.0, 30.0, 40.0}; // A base box 14 | ToughPack hardcase {20.0, 30.0, 40.0}; // A derived box - same size 15 | Carton carton {20.0, 30.0, 40.0, "Plastic"}; // A different derived box 16 | 17 | printVolume(box); // Display volume of base box 18 | printVolume(hardcase); // Display volume of derived box 19 | printVolume(carton); // Display volume of derived box 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_05/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume() const override { return 0.87 * getLength() * getWidth() * getHeight(); } 13 | }; 14 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_06/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_06/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const override 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_06/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume() const override { return 0.87 * getLength() * getWidth() * getHeight(); } 13 | }; 14 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_07/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_07/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | ~Carton() { std::println("Carton destructor called"); } 14 | 15 | // Function to calculate the volume of a Carton object 16 | double volume() const override 17 | { 18 | return std::max(getLength() - 0.5, 0.0) 19 | * std::max(getWidth() - 0.5, 0.0) 20 | * std::max(getHeight() - 0.5, 0.0); 21 | } 22 | 23 | private: 24 | std::string m_material; 25 | }; 26 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_07/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | ~ToughPack() { std::println("ToughPack destructor called"); } 11 | 12 | // Function to calculate volume of a ToughPack allowing 13% for packing 13 | double volume() const override { return 0.87 * getLength() * getWidth() * getHeight(); } 14 | }; 15 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_08/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_08/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const override 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_08/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume() const override { return 0.87 * Box::volume(); } 13 | }; 14 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_09/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_09/Ex15_09.cpp: -------------------------------------------------------------------------------- 1 | // Calling virtual functions from constructors and destructors 2 | import boxes; 3 | 4 | int main() 5 | { 6 | ToughPack toughPack{ 1.0, 2.0, 3.0 }; 7 | toughPack.printVolume(); // Should print a volume equal to 87% of 1x2x3, or 5.22 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_09/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | import :box; 3 | import std; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | ToughPack(double length, double width, double height) 9 | : Box{length, width, height} 10 | { 11 | std::println("ToughPack constructor called for a Box of volume {}", volume()); 12 | } 13 | ~ToughPack() override 14 | { 15 | std::println("ToughPack destructor called for a Box of volume {}", volume()); 16 | } 17 | 18 | // Function to calculate volume of a ToughPack allowing 13% for packing 19 | double volume() const override { return 0.87 * Box::volume(); } 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_10/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_10/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const override 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_11/Box.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box(double l, double w, double h) : m_length {l}, m_width {w}, m_height {h} {} 7 | virtual ~Box() = default; // Virtual destructor 8 | 9 | double getLength() const { return m_length; } 10 | double getWidth() const { return m_width; } 11 | double getHeight() const { return m_height; } 12 | 13 | virtual double volume() const = 0; // Function to calculate the volume 14 | 15 | private: 16 | double m_length, m_width, m_height; 17 | }; 18 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_11/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_11/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const override 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_11/Ex15_11.cpp: -------------------------------------------------------------------------------- 1 | // Using an abstract class 2 | import std; 3 | import boxes; 4 | 5 | int main() 6 | { 7 | // Box box{20.0, 30.0, 40.0}; // Uncomment for compiler error 8 | 9 | ToughPack hardcase {20.0, 30.0, 40.0}; // A derived box - same size 10 | Carton carton {20.0, 30.0, 40.0, "plastic"}; // A different derived box 11 | 12 | Box* base {&hardcase}; // Base pointer - derived address 13 | std::println("hardcase volume is {}", base->volume()); 14 | 15 | base = &carton; // New derived address 16 | std::println("carton volume is {}", base->volume()); 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_11/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume() const override { return 0.87 * getLength() * getWidth() * getHeight(); } 13 | }; 14 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_12/Box.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:box; 2 | 3 | import vessel; 4 | 5 | export class Box : public Vessel 6 | { 7 | public: 8 | Box(double l, double w, double h) : m_length {l}, m_width {w}, m_height {h} {} 9 | 10 | double getLength() const { return m_length; } 11 | double getWidth() const { return m_width; } 12 | double getHeight() const { return m_height; } 13 | 14 | double volume() const override { return m_length * m_width * m_height; } 15 | 16 | private: 17 | double m_length, m_width, m_height; 18 | }; 19 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_12/Boxes.cppm: -------------------------------------------------------------------------------- 1 | // Boxes.cppm: primary module interface file 2 | export module boxes; 3 | 4 | export import :box; // Export all partitions 5 | export import :tough_pack; 6 | export import :carton; -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_12/Can.cppm: -------------------------------------------------------------------------------- 1 | // Can.cppm Class defining a cylindrical can of a given height and diameter 2 | export module can; 3 | 4 | import vessel; 5 | import std; 6 | 7 | export class Can : public Vessel 8 | { 9 | public: 10 | Can(double diameter, double height) 11 | : m_diameter {diameter}, m_height {height} {} 12 | 13 | double volume() const override 14 | { 15 | return std::numbers::pi * m_diameter * m_diameter * m_height / 4; 16 | } 17 | 18 | private: 19 | double m_diameter, m_height; 20 | }; 21 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_12/Carton.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:carton; 2 | import :box; 3 | import std; 4 | 5 | export class Carton : public Box 6 | { 7 | public: 8 | // Constructor explicitly calling the base constructor 9 | Carton(double l, double w, double h, std::string_view mat = "cardboard") 10 | : Box{l, w, h}, m_material{mat} 11 | {} 12 | 13 | // Function to calculate the volume of a Carton object 14 | double volume() const override 15 | { 16 | return std::max(getLength() - 0.5, 0.0) 17 | * std::max(getWidth() - 0.5, 0.0) 18 | * std::max(getHeight() - 0.5, 0.0); 19 | } 20 | 21 | private: 22 | std::string m_material; 23 | }; 24 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_12/Ex15_12.cpp: -------------------------------------------------------------------------------- 1 | // Using an interface class and indirect base classes 2 | import std; 3 | import boxes; 4 | import vessel; 5 | import can; 6 | 7 | int main() 8 | { 9 | Box box {40, 30, 20}; 10 | Can can {10, 3}; 11 | Carton carton {40, 30, 20, "Plastic"}; 12 | ToughPack hardcase {40, 30, 20}; 13 | 14 | std::vector vessels {&box, &can, &carton, &hardcase}; 15 | 16 | for (const auto* vessel : vessels) 17 | std::println("Volume is {:.6}", vessel->volume()); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_12/ToughPack.cppm: -------------------------------------------------------------------------------- 1 | export module boxes:tough_pack; 2 | 3 | import :box; 4 | 5 | export class ToughPack : public Box 6 | { 7 | public: 8 | // Inherit the Box(length, width, height) constructor 9 | using Box::Box; 10 | 11 | // Function to calculate volume of a ToughPack allowing 13% for packing 12 | double volume() const override { return 0.87 * Box::volume(); } 13 | }; 14 | -------------------------------------------------------------------------------- /Examples/Chapter 15/Ex15_12/Vessel.cppm: -------------------------------------------------------------------------------- 1 | // Vessel.cppm Abstract class defining a vessel 2 | export module vessel; 3 | 4 | export class Vessel 5 | { 6 | public: 7 | virtual ~Vessel() = default; // As always: a virtual destructor! 8 | virtual double volume() const = 0; 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_02/Ex16_02.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Examples/Chapter 16/Ex16_02/Ex16_02.cpp -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_02/Troubles.cppm: -------------------------------------------------------------------------------- 1 | // Exception class definition 2 | export module troubles; 3 | import std; 4 | 5 | export class Trouble 6 | { 7 | public: 8 | explicit Trouble(std::string_view message = "There's a problem") 9 | : m_message {message} 10 | {} 11 | std::string_view what() const { return m_message; } 12 | private: 13 | std::string m_message; 14 | }; 15 | -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_04/Ex16_04.cpp: -------------------------------------------------------------------------------- 1 | // Catching exceptions with a base class handler 2 | import std; 3 | import troubles; 4 | 5 | int main() 6 | { 7 | for (int i {}; i < 7; ++i) 8 | { 9 | try 10 | { 11 | if (i == 3) 12 | throw Trouble{}; 13 | else if (i == 5) 14 | throw MoreTrouble{}; 15 | else if (i == 6) 16 | throw BigTrouble{}; 17 | } 18 | catch (const Trouble& t) 19 | { 20 | std::println("Trouble object caught: {}", t.what()); 21 | // std::println("{} object caught: {}", typeid(t).name(), t.what()); 22 | } 23 | std::println("End of the for loop (after the catch blocks) - i is {}", i); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_08/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | import std; 3 | import dimension_error; 4 | 5 | export class Box 6 | { 7 | public: 8 | Box(double l, double w, double h) : m_length{ l }, m_width{ w }, m_height{ h } 9 | { 10 | if (l <= 0.0 || w <= 0.0 || h <= 0.0) 11 | throw DimensionError{ std::min({l, w, h}) }; 12 | } 13 | 14 | double volume() const { return m_length * m_width * m_height; } 15 | private: 16 | double m_length{ 1.0 }; 17 | double m_width{ 1.0 }; 18 | double m_height{ 1.0 }; 19 | }; 20 | -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_08/DimensionError.cppm: -------------------------------------------------------------------------------- 1 | export module dimension_error; 2 | 3 | import std; 4 | 5 | export class DimensionError : public std::out_of_range 6 | { 7 | public: 8 | explicit DimensionError(double value) 9 | : std::out_of_range{ "Zero or negative dimension: " + std::to_string(value) } 10 | , m_value{ value } {} 11 | 12 | // Function to obtain the invalid dimension value 13 | double getValue() const noexcept { return m_value; } 14 | private: 15 | double m_value; 16 | }; 17 | -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_08/Ex16_08.cpp: -------------------------------------------------------------------------------- 1 | // Using an exception class 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | try 8 | { 9 | Box box1 {1.0, 2.0, 3.0}; 10 | std::println("box1 volume is {}", box1.volume()); 11 | Box box2 {1.0, -2.0, 3.0}; 12 | std::println("box2 volume is {}", box2.volume()); 13 | } 14 | catch (const std::exception& ex) 15 | { 16 | std::println("Exception caught in main(): {}", ex.what()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_09/Ex16_09.cpp: -------------------------------------------------------------------------------- 1 | // Embedding a stack trace in an exception 2 | import std; 3 | import tracing; 4 | 5 | int f3() { throw TracingException{ "Something's amiss!" }; } // Obtains a stacktrace! 6 | int f2() { return f3(); } 7 | int f1() { return f2(); } 8 | 9 | int main() 10 | { 11 | try 12 | { 13 | f1(); 14 | } 15 | catch (const TracingException& ex) 16 | { 17 | std::println("Exception of type {} caught: {}; trace:\n{}", 18 | typeid(ex).name(), ex.what(), ex.where()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Chapter 16/Ex16_09/Tracing.cppm: -------------------------------------------------------------------------------- 1 | // A custom exception class that carries a stack trace 2 | export module tracing; 3 | import std; 4 | 5 | export class TracingException : public std::exception 6 | { 7 | public: 8 | TracingException(std::string_view message, 9 | std::stacktrace trace = std::stacktrace::current()) //<-- Magic happens here! 10 | : m_message{ message } 11 | , m_trace{ trace } 12 | {} 13 | 14 | const char* what() const noexcept override { return m_message.c_str(); } 15 | const auto& where() const noexcept { return m_trace; } 16 | 17 | private: 18 | std::string m_message; 19 | std::stacktrace m_trace; 20 | }; -------------------------------------------------------------------------------- /Examples/Chapter 17/Ex17_01/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() : Box{ 1.0, 1.0, 1.0 } {} 7 | Box(double l, double w, double h) : m_length{ l }, m_width{ w }, m_height{ h } {} 8 | 9 | double volume() const { return m_length * m_width * m_height; } 10 | private: 11 | double m_length, m_width, m_height; 12 | }; 13 | -------------------------------------------------------------------------------- /Examples/Chapter 17/Ex17_01A/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() : Box{ 1.0, 1.0, 1.0 } {} 7 | Box(double l, double w, double h) : m_length{ l }, m_width{ w }, m_height{ h } {} 8 | 9 | double volume() const { return m_length * m_width * m_height; } 10 | private: 11 | double m_length, m_width, m_height; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /Examples/Chapter 17/Ex17_02/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() : Box{ 1.0, 1.0, 1.0 } {} 7 | Box(double l, double w, double h) : m_length{ l }, m_width{ w }, m_height{ h } {} 8 | 9 | double volume() const { return m_length * m_width * m_height; } 10 | private: 11 | double m_length, m_width, m_height; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /Examples/Chapter 17/Ex17_02A/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() : Box{ 1.0, 1.0, 1.0 } {} 7 | Box(double l, double w, double h) : m_length{ l }, m_width{ w }, m_height{ h } {} 8 | 9 | double volume() const { return m_length * m_width * m_height; } 10 | private: 11 | double m_length, m_width, m_height; 12 | }; 13 | -------------------------------------------------------------------------------- /Examples/Chapter 17/Ex17_03/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() : Box{ 1.0, 1.0, 1.0 } {} 7 | Box(double l, double w, double h) : m_length{ l }, m_width{ w }, m_height{ h } {} 8 | 9 | double volume() const { return m_length * m_width * m_height; } 10 | private: 11 | double m_length, m_width, m_height; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /Examples/Chapter 17/Ex17_05/Ex17_05A.cpp: -------------------------------------------------------------------------------- 1 | // Disambiguating dependant names: this code will not compile. 2 | 3 | template 4 | class Outer 5 | { 6 | public: 7 | class Nested { /* ... */ }; // Or a type alias of form 'using Nested = ...;' 8 | // ... 9 | }; 10 | 11 | // Uncomment the typename keyword to turn Outer::Nested into 12 | // a dependent type name and fix the compilation 13 | template 14 | void someFunction() { /*typename*/ Outer::Nested* nested; /* ... */ } 15 | -------------------------------------------------------------------------------- /Examples/Chapter 17/Ex17_05/Ex17_05B.cpp: -------------------------------------------------------------------------------- 1 | // Disambiguating dependant names 2 | // Note: not all compilers may implement the C++20 rules already, 3 | // any may still require additional typename keywords in front of T::Derived 4 | 5 | template // T assumed to define nested Base and Derived types / aliases 6 | T::Base someOtherFunction() 7 | { 8 | typename T::Base* b{ new T::Derived{} }; // Or: auto* b{ ... } 9 | const typename T::Derived& d{ static_cast(*b) }; // Or: const auto& d{ ... } 10 | /* ... */ 11 | return b; 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_02/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, bool (*compare)(const T&, const T&)) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_03/Ex19_03.cpp: -------------------------------------------------------------------------------- 1 | // Exercising the use of a functor as callback functions 2 | import std; 3 | import optimum; 4 | import less; 5 | 6 | template 7 | bool greater(const T& one, const T& other) { return one > other; } 8 | 9 | int main() 10 | { 11 | Less less; // Create a 'less than' functor 12 | 13 | std::vector numbers{ 91, 18, 92, 22, 13, 43 }; 14 | std::println("Minimum element: {}", *findOptimum(numbers, less)); 15 | std::println("Maximum element: {}", *findOptimum(numbers, greater)); 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_03/Less.cppm: -------------------------------------------------------------------------------- 1 | // Less.cppm - A basic class of functor objects 2 | export module less; 3 | 4 | export class Less 5 | { 6 | public: 7 | #ifdef __cpp_static_call_operator // Not all compilers support static operators yet 8 | static bool operator()(int a, int b) { return a < b; } 9 | #else 10 | bool operator()(int a, int b) const { return a < b; } 11 | #endif 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_03/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_03A/Ex19_03A.cpp: -------------------------------------------------------------------------------- 1 | // Exercising the use of standard functors 2 | import std; 3 | import optimum; 4 | 5 | int main() 6 | { 7 | std::vector numbers{ 91, 18, 92, 22, 13, 43 }; 8 | std::println("Minimum element: {}", *findOptimum(numbers, std::less<>{})); 9 | std::println("Maximum element: {}", *findOptimum(numbers, std::greater<>{})); 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_03A/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_04/Ex19_04.cpp: -------------------------------------------------------------------------------- 1 | // Exercising a function object with a member variable 2 | import std; 3 | import optimum; 4 | import nearer; 5 | 6 | int main() 7 | { 8 | std::vector numbers{ 91, 18, 92, 22, 13, 43 }; 9 | 10 | int number_to_search_for {}; 11 | std::print("Please enter a number: "); 12 | std::cin >> number_to_search_for; 13 | 14 | std::println("The number nearest to {} is {}", 15 | number_to_search_for, *findOptimum(numbers, Nearer{ number_to_search_for })); 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_04/Nearer.cppm: -------------------------------------------------------------------------------- 1 | // A class of function objects that compare two values based on how close they are 2 | // to some third value that was provided to the functor at construction time. 3 | export module nearer; 4 | import std; // For std::abs() 5 | 6 | export class Nearer 7 | { 8 | public: 9 | explicit Nearer(int value) : m_value{ value } {} 10 | bool operator()(int x, int y) const 11 | { 12 | return std::abs(x - m_value) < std::abs(y - m_value); 13 | } 14 | private: 15 | int m_value; 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_04/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_05/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_05A/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_05B/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_06/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_07/Ex19_07.cpp: -------------------------------------------------------------------------------- 1 | // Using a lambda expression from inside a member function (see Finder.cpp) 2 | import std; 3 | import optimum; 4 | import finder; 5 | 6 | int main() 7 | { 8 | std::vector numbers{ 91, 18, 92, 22, 13, 43 }; 9 | 10 | int number_to_search_for {}; 11 | std::print("Please enter a number: "); 12 | std::cin >> number_to_search_for; 13 | 14 | Finder finder; 15 | finder.setNumberToSearchFor(number_to_search_for); 16 | std::println("The number nearest to {} is {}", 17 | finder.getNumberToSearchFor(), *finder.findNearest(numbers)); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_07/Finder.cpp: -------------------------------------------------------------------------------- 1 | // Exercising capturing the this pointer 2 | module finder; 3 | 4 | import std; 5 | import optimum; 6 | 7 | std::optional Finder::findNearest(const std::vector& values) const 8 | { 9 | if (values.empty()) 10 | return std::nullopt; 11 | else 12 | return *findOptimum(values, [this](double x, double y) { 13 | return std::abs(x - m_number_to_search_for) < std::abs(y - m_number_to_search_for); 14 | }); 15 | } 16 | 17 | double Finder::getNumberToSearchFor() const 18 | { 19 | return m_number_to_search_for; 20 | } 21 | 22 | void Finder::setNumberToSearchFor(double value) 23 | { 24 | m_number_to_search_for = value; 25 | } -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_07/Finder.cppm: -------------------------------------------------------------------------------- 1 | // Finder.cppm - A small class to illustrate the use of lambda expression in member functions 2 | export module finder; 3 | 4 | import std; 5 | 6 | export class Finder 7 | { 8 | public: 9 | double getNumberToSearchFor() const; 10 | void setNumberToSearchFor(double n); 11 | 12 | std::optional findNearest(const std::vector& values) const; 13 | private: 14 | double m_number_to_search_for {}; 15 | }; 16 | -------------------------------------------------------------------------------- /Examples/Chapter 19/Ex19_07/Optimum.cppm: -------------------------------------------------------------------------------- 1 | // Optimum.cppm - a function template to determine the optimum element in a given vector 2 | export module optimum; 3 | 4 | import std; 5 | 6 | export template 7 | const T* findOptimum(const std::vector& values, Comparison compare) 8 | { 9 | if (values.empty()) return nullptr; 10 | 11 | const T* optimum{ &values[0] }; 12 | for (std::size_t i {1}; i < values.size(); ++i) 13 | { 14 | if (compare(values[i], *optimum)) 15 | optimum = &values[i]; 16 | } 17 | return optimum; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_01/Ex20_01.cpp: -------------------------------------------------------------------------------- 1 | // Working with std::deque<> 2 | import std; 3 | 4 | int main() 5 | { 6 | std::deque my_deque; // A deque<> allows efficient insertions 7 | my_deque.push_back(2); // to both ends of the sequence 8 | my_deque.push_back(4); 9 | my_deque.push_front(1); 10 | 11 | my_deque[2] = 3; // A deque<> is a random-access sequence container 12 | 13 | std::print("There are {} elements in my_deque: ", my_deque.size()); 14 | 15 | for (int element : my_deque) // A deque<>, like all containers, is a range 16 | std::print("{} ", element); 17 | std::println(""); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_04/Ex20_04.cpp: -------------------------------------------------------------------------------- 1 | // Basic use of std::map<> 2 | import std; 3 | 4 | int main() 5 | { 6 | std::map phone_book; 7 | phone_book["Joe"] = 202'456'1111; 8 | phone_book["Jill"] = 202'456'1111; 9 | phone_book["Francis"] = 39'06'6982; 10 | phone_book["Charles"] = 44'020'7930'4832; 11 | 12 | std::println("The pope's number is {}", phone_book["Francis"]); 13 | 14 | for (const auto& [name, number] : phone_book) 15 | std::println("{} can be reached at {}", name, number); 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_07/Ex20_07.cpp: -------------------------------------------------------------------------------- 1 | // Iterating over the elements of a list<> 2 | import std; 3 | 4 | int main() 5 | { 6 | std::print("Enter a sequence of positive numbers, terminated by -1:"); 7 | 8 | std::list numbers; 9 | 10 | while (true) 11 | { 12 | signed number{-1}; 13 | std::cin >> number; 14 | if (number == -1) break; 15 | numbers.push_back(static_cast(number)); 16 | } 17 | 18 | std::print("You entered the following numbers:"); 19 | for (auto iter {numbers.begin()}; iter != numbers.end(); ++iter) 20 | { 21 | std::print("{} ", *iter); 22 | } 23 | std::println(""); 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_08/Ex20_08.cpp: -------------------------------------------------------------------------------- 1 | // Altering elements through a mutable iterator 2 | import std; 3 | import box; // From Ex11_04 4 | 5 | int main() 6 | { 7 | std::vector boxes{ Box{ 1.0, 2.0, 3.0 } }; // A std::vector containing 1 Box 8 | 9 | auto iter{ boxes.begin() }; 10 | std::println("{} ", iter->volume()); // 6 == 1.0 * 2.0 * 3.0 11 | 12 | *iter = Box{ 2.0, 3.0, 4.0 }; 13 | std::println("{} ", iter->volume()); // 24 == 2.0 * 3.0 * 4.0 14 | 15 | iter->setHeight(7.0); 16 | std::println("{} ", iter->volume()); // 42 == 2.0 * 3.0 * 7.0 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_13A/Ex20_13A.cpp: -------------------------------------------------------------------------------- 1 | // Extracting all odd numbers using std::back_inserter(). 2 | import std; 3 | 4 | std::set fillSet_1toN(int N); // Fill a set with 1, 2, ..., N 5 | 6 | int main() 7 | { 8 | const int num_numbers{20}; 9 | 10 | const auto numbers{ fillSet_1toN(num_numbers) }; 11 | 12 | std::vector odd_numbers; 13 | std::copy_if(begin(numbers), end(numbers), back_inserter(odd_numbers), 14 | [](int n) { return n % 2 == 1; }); 15 | 16 | std::println("The odd numbers are: {:n}", odd_numbers); 17 | } 18 | 19 | std::set fillSet_1toN(int N) // Fill a set with 1, 2, ..., N 20 | { 21 | std::set numbers; 22 | for (int i{ 1 }; i <= N; ++i) 23 | numbers.insert(i); 24 | return numbers; 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_15/Ex20_15.cpp: -------------------------------------------------------------------------------- 1 | // Sorting strings 2 | import std; 3 | 4 | int main() 5 | { 6 | std::vector names{"Frodo Baggins", "Gandalf the Gray", 7 | "Aragon", "Samwise Gamgee", "Peregrin Took", "Meriadoc Brandybuck", 8 | "Gimli", "Legolas Greenleaf", "Boromir"}; 9 | 10 | // Sort the names lexicographically 11 | std::sort(begin(names), end(names)); 12 | std::println("Names sorted lexicographically: {:n}", names); 13 | 14 | // Sort the names by length 15 | std::sort(begin(names), end(names), 16 | [](const auto& left, const auto& right) { return left.length() < right.length(); }); 17 | std::println("Names sorted by length: {:n}", names); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_15A/Ex20_15A.cpp: -------------------------------------------------------------------------------- 1 | // Sorting strings using range-based sort() 2 | import std; 3 | 4 | int main() 5 | { 6 | std::vector names{"Frodo Baggins", "Gandalf the Gray", 7 | "Aragon", "Samwise Gamgee", "Peregrin Took", "Meriadoc Brandybuck", 8 | "Gimli", "Legolas Greenleaf", "Boromir"}; 9 | 10 | // Sort the names lexicographically 11 | std::ranges::sort(names); 12 | std::println("Names sorted lexicographically: {:n}", names); 13 | 14 | // Sort the names by length 15 | std::ranges::sort(names, [](const auto& left, const auto& right) {return left.length() < right.length(); }); 16 | std::println("Names sorted by length: {:n}", names); 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_17/Ex20_17.cpp: -------------------------------------------------------------------------------- 1 | // Range factories and range adaptors 2 | import std; 3 | 4 | using namespace std::ranges::views; 5 | 6 | bool isEven(int i) { return i % 2 == 0; } 7 | int squared(int i) { return i * i; } 8 | 9 | int main() 10 | { 11 | for (int i : iota(1, 10)) // Lazily generate range [1,10) 12 | std::print("{} ", i); 13 | std::println(""); 14 | 15 | for (int i : iota(1, 1000) | filter(isEven) | transform(squared) 16 | | drop(2) | take(5) | reverse) 17 | std::print("{} ", i); 18 | std::println(""); 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Chapter 20/Ex20_18/Ex20_18.cpp: -------------------------------------------------------------------------------- 1 | // Writing through a view 2 | import std; 3 | 4 | bool isEven(int i) { return i % 2 == 0; } 5 | 6 | int main() 7 | { 8 | std::vector numbers{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 9 | 10 | for (int& i : numbers | std::views::filter(isEven)) 11 | i *= i; 12 | 13 | std::println("{}", numbers); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Chapter 21/Ex21_01/Ex21_01.cpp: -------------------------------------------------------------------------------- 1 | // Class template instantiation errors 2 | import std; 3 | 4 | class MyClass { /* just a dummy class */ }; 5 | 6 | int main() 7 | { 8 | std::vector v; 9 | 10 | MyClass one, other; 11 | auto biggest{ std::max(one, other) }; 12 | 13 | std::set objects; 14 | objects.insert(MyClass{}); 15 | 16 | std::list numbers{ 4, 1, 3, 2 }; 17 | std::sort(begin(numbers), end(numbers)); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Chapter 21/Ex21_03/Ex21_03.cpp: -------------------------------------------------------------------------------- 1 | // Violating constraints of uninstantiated class members 2 | import array; 3 | import std; 4 | 5 | // Assert that Array> is a valid type 6 | static_assert(requires { typename Array>; }); 7 | 8 | int main() 9 | { 10 | Array> tenSmartPointers(10); 11 | Array> target; 12 | // target = tenSmartPointers; /* Constraint not satisfied: copyable */ 13 | target = std::move(tenSmartPointers); 14 | target.push_back(std::make_unique(123)); 15 | } 16 | -------------------------------------------------------------------------------- /Examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | This directory contains all source code for the examples given 4 | in [*Beginning C++23*](https://www.apress.com/9781484258835) by Ivor Horton and Peter Van Weert (Apress, 2023). 5 | 6 | Consult the [Workarounds](../Workarounds) directory on 7 | how to work around compilation issues with C++23 language and library features 8 | that your compiler may not (fully) [support](https://en.cppreference.com/w/cpp/compiler_support). 9 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_01/SolnA_01.cpp: -------------------------------------------------------------------------------- 1 | // Exercise A-1 Defining a function-like macro 2 | 3 | // import std; /* This does not work with Visual Studio 17 preview: using #include instead... */ 4 | #include 5 | #include "ASSERT.h" 6 | 7 | int main() 8 | { 9 | int y{ 5 }; 10 | 11 | for (int x{}; x < 20; ++x) 12 | { 13 | std::println("x = {}\ty = {}", x, y); 14 | ASSERT(x < y, "Whoops-a-daisy, too far!"); 15 | } 16 | } -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_02/ASSERT.h: -------------------------------------------------------------------------------- 1 | #ifndef ASSERT_H 2 | #define ASSERT_H 3 | 4 | #include 5 | #include 6 | 7 | #ifndef NDEBUG 8 | #define ASSERT(condition, message) \ 9 | if (!(condition)) \ 10 | { \ 11 | std::cerr << (message) << std::endl; \ 12 | std::abort(); \ 13 | } 14 | #else 15 | #define ASSERT(condition, message) 16 | #endif 17 | 18 | #endif // End of the #include guard -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_02/SolnA_02.cpp: -------------------------------------------------------------------------------- 1 | // import std; /* This does not work with Visual Studio 17 preview: using #include instead... */ 2 | #include 3 | 4 | // Define (before including ASSERT.h) to disable the assertion 5 | #define NDEBUG 6 | #include "ASSERT.h" 7 | 8 | int main() 9 | { 10 | int y{ 5 }; 11 | 12 | for (int x{}; x < 20; ++x) 13 | { 14 | std::println("x = {}\ty = {}", x, y); 15 | ASSERT(x < y, "Whoops-a-daisy, too far!"); 16 | } 17 | } -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_03/SmarterException.cpp: -------------------------------------------------------------------------------- 1 | #include "SmarterException.h" 2 | 3 | SmarterException::SmarterException(const std::string& message, std::source_location location) 4 | : std::logic_error{ message } 5 | , m_location{ std::move(location) } 6 | { 7 | } 8 | 9 | const std::source_location& SmarterException::where() const 10 | { 11 | return m_location; 12 | } 13 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_03/SmarterException.h: -------------------------------------------------------------------------------- 1 | #ifndef SMARTER_EXCEPTION_H 2 | #define SMARTER_EXCEPTION_H 3 | 4 | #include 5 | #include 6 | 7 | class SmarterException : public std::logic_error 8 | { 9 | public: 10 | SmarterException(const std::string& message, std::source_location location = std::source_location::current()); 11 | 12 | const std::source_location& where() const; 13 | 14 | private: 15 | std::source_location m_location; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_03/SolnA_03.cpp: -------------------------------------------------------------------------------- 1 | // Exercise A-3 Writing an exception class that records where 2 | // the exception object was created/thrown. 3 | 4 | // import std; /* This does not work with Visual Studio 17 preview: using #include instead... */ 5 | #include 6 | #include "SmarterException.h" 7 | 8 | int main() 9 | { 10 | try 11 | { 12 | throw SmarterException{ "Throwing directly..." }; 13 | } 14 | catch (const SmarterException& exception) 15 | { 16 | std::println("Something went wrong at line {}", exception.where().line()); 17 | } 18 | } -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_04/SmarterException.h: -------------------------------------------------------------------------------- 1 | #ifndef SMARTER_EXCEPTION_H 2 | #define SMARTER_EXCEPTION_H 3 | 4 | #include 5 | #include 6 | 7 | class SmarterException : public std::logic_error 8 | { 9 | public: 10 | SmarterException(const std::string& message, std::source_location location = std::source_location::current()) 11 | : std::logic_error{ message } 12 | , m_location{ std::move(location) } 13 | { 14 | } 15 | 16 | const std::source_location& where() const; 17 | 18 | private: 19 | std::source_location m_location; 20 | }; 21 | 22 | inline const std::source_location& SmarterException::where() const 23 | { 24 | return m_location; 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_04/SolnA_04.cpp: -------------------------------------------------------------------------------- 1 | // Exercise A-4 Defining class member functions in the header 2 | 3 | // import std; /* This does not work with Visual Studio 17 preview: using #include instead... */ 4 | #include 5 | #include "SmarterException.h" 6 | 7 | int main() 8 | { 9 | try 10 | { 11 | throw SmarterException{ "Throwing directly..." }; 12 | } 13 | catch (const SmarterException& exception) 14 | { 15 | std::println("Something went wrong at line {}", exception.where().line()); 16 | } 17 | } -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_05/Print.cpp: -------------------------------------------------------------------------------- 1 | import std; 2 | 3 | void print(std::string_view string) 4 | { 5 | std::println("{}", string); 6 | } 7 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_05/PrintThat.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThat.h" 2 | 3 | // Note: extern keyword is optional, 4 | // but does make clear that external linkage is used here. 5 | extern void print(std::string_view string); 6 | 7 | void print_that(std::string_view string) 8 | { 9 | print(string); 10 | } 11 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_05/PrintThat.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THAT_H 5 | #define PRINT_THAT_H 6 | 7 | #include 8 | 9 | void print_that(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_05/PrintThis.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThis.h" 2 | 3 | // Note: extern keyword is optional, 4 | // but does make clear that external linkage is used here. 5 | extern void print(std::string_view string); 6 | 7 | void print_this(std::string_view string) 8 | { 9 | print(string); 10 | } 11 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_05/PrintThis.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THIS_H 5 | #define PRINT_THIS_H 6 | 7 | #include 8 | 9 | void print_this(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_05/SolnA_05.cpp: -------------------------------------------------------------------------------- 1 | // Exercise A-5 External functions and header files... 2 | #include "PrintThis.h" 3 | #include "PrintThat.h" 4 | 5 | int main() 6 | { 7 | print_this("Happiness can be found even in the darkest of times, "); 8 | print_that("if one only remembers to turn on the light."); 9 | // -- Albus Dumbledore 10 | } -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_06/Print.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_H 2 | #define PRINT_H 3 | 4 | // Caution: no imports in header files... 5 | #include 6 | #include 7 | 8 | inline void print(std::string_view string) 9 | { 10 | std::println("{}", string); 11 | } 12 | 13 | #endif -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_06/PrintThat.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThat.h" 2 | #include "Print.h" 3 | 4 | void print_that(std::string_view string) 5 | { 6 | print(string); 7 | } 8 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_06/PrintThat.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THAT_H 5 | #define PRINT_THAT_H 6 | 7 | #include 8 | 9 | void print_that(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_06/PrintThis.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThis.h" 2 | #include "Print.h" 3 | 4 | void print_this(std::string_view string) 5 | { 6 | print(string); 7 | } 8 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_06/PrintThis.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THIS_H 5 | #define PRINT_THIS_H 6 | 7 | #include 8 | 9 | void print_this(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_06/SolnA_06.cpp: -------------------------------------------------------------------------------- 1 | // Exercise A-6 Inline function definitions 2 | #include "PrintThis.h" 3 | #include "PrintThat.h" 4 | 5 | int main() 6 | { 7 | print_this("I have found that it is the small everyday deed of ordinary folks "); 8 | print_that("that keep the darkness at bay. Small acts of kindness and love."); 9 | // -- Gandalf the Grey 10 | } -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07A/Print.cpp: -------------------------------------------------------------------------------- 1 | import std; 2 | 3 | unsigned count; 4 | 5 | void print(std::string_view string) 6 | { 7 | std::println("{}", string); 8 | ++count; 9 | } 10 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07A/PrintThat.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThat.h" 2 | 3 | // Note: extern keyword is optional, 4 | // but does make clear that external linkage is used here. 5 | extern void print(std::string_view string); 6 | 7 | void print_that(std::string_view string) 8 | { 9 | print(string); 10 | } 11 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07A/PrintThat.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THAT_H 5 | #define PRINT_THAT_H 6 | 7 | #include 8 | 9 | void print_that(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07A/PrintThis.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThis.h" 2 | 3 | // Note: extern keyword is optional, 4 | // but does make clear that external linkage is used here. 5 | extern void print(std::string_view string); 6 | 7 | void print_this(std::string_view string) 8 | { 9 | print(string); 10 | } 11 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07A/PrintThis.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THIS_H 5 | #define PRINT_THIS_H 6 | 7 | #include 8 | 9 | void print_this(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07A/SolnA_07A.cpp: -------------------------------------------------------------------------------- 1 | // Exercise A-7 External variables (based on Exercise A-5) 2 | 3 | // import std; /* This does not work with Visual Studio 17 preview: using #include instead... */ 4 | #include 5 | 6 | #include "PrintThis.h" 7 | #include "PrintThat.h" 8 | 9 | extern unsigned count; 10 | 11 | int main() 12 | { 13 | print_this("It is our choices that show what we truly are, "); 14 | print_that("far more than our abilities."); 15 | // -- Albus Dumbledore 16 | 17 | std::println("\n(print() was called {} times)", count); 18 | } -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07B/Print.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_H 2 | #define PRINT_H 3 | 4 | // Caution: no imports in header files... 5 | #include 6 | #include 7 | 8 | inline int count {}; 9 | 10 | inline void print(std::string_view string) 11 | { 12 | std::println("{}", string); 13 | ++count; 14 | } 15 | 16 | #endif -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07B/PrintThat.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThat.h" 2 | #include "Print.h" 3 | 4 | void print_that(std::string_view string) 5 | { 6 | print(string); 7 | } 8 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07B/PrintThat.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THAT_H 5 | #define PRINT_THAT_H 6 | 7 | #include 8 | 9 | void print_that(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07B/PrintThis.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintThis.h" 2 | #include "Print.h" 3 | 4 | void print_this(std::string_view string) 5 | { 6 | print(string); 7 | } 8 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07B/PrintThis.h: -------------------------------------------------------------------------------- 1 | // Note: #include guards are strictly speaking optional for headers 2 | // that contain only function prototypes, 3 | // but convention dictates you add them regardless. 4 | #ifndef PRINT_THIS_H 5 | #define PRINT_THIS_H 6 | 7 | #include 8 | 9 | void print_this(std::string_view string); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Exercises/Appendix A/SolnA_07B/SolnA_07B.cpp: -------------------------------------------------------------------------------- 1 | // Exercise A-7 External variables (based on Exercise A-6) 2 | 3 | // import std; /* This does not work with Visual Studio 17 preview: using #include instead... */ 4 | #include 5 | 6 | #include "PrintThis.h" 7 | #include "PrintThat.h" 8 | #include "Print.h" 9 | 10 | int main() 11 | { 12 | print_this("All we have to decide is what to do "); 13 | print_that("with the time that is given to us."); 14 | // -- Gandalf the Grey 15 | 16 | std::println("\n(print() was called {} times)", count); 17 | } -------------------------------------------------------------------------------- /Exercises/Chapter 01/Soln1_01.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 1-1 Writing the line "Hello World" to the screen. 2 | 3 | import std; 4 | 5 | int main() 6 | { 7 | std::println("Hello World"); 8 | } -------------------------------------------------------------------------------- /Exercises/Chapter 01/Soln1_02.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 1-2. Write your name and age on successive lines. 2 | // There are several possibilities. You can do it in one statement for example, 3 | // using '\n' to go to a new line. 4 | 5 | import std; 6 | 7 | int main() 8 | { 9 | int age{ 88 }; 10 | std::println("Phil McCavity"); // Name 11 | std::println("Age: {}", age); // and age 12 | } -------------------------------------------------------------------------------- /Exercises/Chapter 02/Soln2_03.cpp: -------------------------------------------------------------------------------- 1 | // Compute the area of a circle 2 | // This solution tunes the precision used when printing the result 3 | // (we opted for 2 decimals after the decimal points). 4 | 5 | import std; 6 | 7 | int main() 8 | { 9 | std::println("This program will compute the area of a circle."); 10 | 11 | double radius {}; 12 | std::print("Please enter the radius of the circle: "); 13 | std::cin >> radius; 14 | 15 | const auto area{ std::numbers::pi * radius * radius }; 16 | 17 | std::println("The area of the circle is {:.2f} square units.", area); 18 | } -------------------------------------------------------------------------------- /Exercises/Chapter 02/Soln2_07.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 2-6. Format a table. 2 | 3 | import std; 4 | 5 | int main() 6 | { 7 | std::println("{:20} {:35} {}", "Constant", "Description", "Approximation"); 8 | std::println("{:20} {:35} {:.5f}...", "std::numbers::e", "The base of the natural logarithm", std::numbers::e); 9 | std::println("{:20} {:35} {:.5f}...", "std::numbers::pi", "pi", std::numbers::pi); 10 | std::println("{:20} {:35} {:.5f}...", "std::numbers::sqrt2", "Square root of 2", std::numbers::sqrt2); 11 | std::println("{:20} {:35} {:.3f}...", "std::numbers::phi", "The golden ratio constant", std::numbers::phi); 12 | } -------------------------------------------------------------------------------- /Exercises/Chapter 03/Soln3_06.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 3-6. Swapping integers. 2 | 3 | import std; 4 | 5 | int main() 6 | { 7 | int first {}, second {}; 8 | std::print("Enter two integers separated by a space: "); 9 | std::cin >> first >> second; 10 | 11 | first ^= second; 12 | second ^= first; 13 | first ^= second; 14 | std::println("In reverse order they are {} and {}", first, second); 15 | } -------------------------------------------------------------------------------- /Exercises/Chapter 04/Soln4_01.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 4-1 Testing whether two integer values are equal. 2 | 3 | import std; 4 | 5 | int main() 6 | { 7 | int value1 {}; 8 | int value2 {}; 9 | 10 | std::print("Please input two integers, separated by a space: "); 11 | std::cin >> value1 >> value2; 12 | std::println(""); 13 | 14 | if (value1 == value2) 15 | std::println("The values you entered are the same (two times {}).", value1); 16 | else 17 | std::println("The values you entered are not the same ({} != {}).", value1, value2); 18 | } -------------------------------------------------------------------------------- /Exercises/Chapter 04/Soln4_03.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 4-3 Using nested ifs and a logical && to check the value of a number. 2 | 3 | import std; 4 | 5 | int main() 6 | { 7 | double value {}; 8 | 9 | std::print("Please enter a number between 1 and 100: "); 10 | std::cin >> value; 11 | std::println(""); 12 | 13 | std::print("The number you entered, {}, is ", value); 14 | 15 | if (value >= 1 && value <= 100) 16 | { 17 | if (value > 50) 18 | std::print("greater than"); 19 | else if (value < 50) 20 | std::print("less than"); 21 | else 22 | std::print("equal to"); 23 | 24 | std::println(" 50."); 25 | } 26 | else 27 | { 28 | std::println("not between 1 and 100."); 29 | } 30 | } -------------------------------------------------------------------------------- /Exercises/Chapter 04/Soln4_06.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 4-6 Finding the range for an integer. 2 | // This is just a question of bolting sufficient conditional operators together 3 | // in an expression. 4 | 5 | import std; 6 | 7 | int main() 8 | { 9 | int n {}; 10 | std::print("Enter an integer: "); 11 | std::cin >> n; 12 | 13 | std::println("The value is {}.", 14 | n <= 20 ? "not greater than 20" : 15 | n <= 30 ? "greater than 20 and not greater than 30" : 16 | n <= 100 ? "greater than 30 and not exceeding 100" : 17 | "greater than 100" 18 | ); 19 | } -------------------------------------------------------------------------------- /Exercises/Chapter 05/Soln5_01.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 5-1 Squaring odd numbers 2 | import std; 3 | 4 | int main() 5 | { 6 | unsigned long long limit {}; 7 | std::print("Enter the upper limit for squared odd numbers: "); 8 | std::cin >> limit; 9 | for (unsigned long long i {1}; i <= limit; i += 2) 10 | { 11 | std::println("{:4} squared is {:8}", i, i * i); 12 | } 13 | } -------------------------------------------------------------------------------- /Exercises/Chapter 05/Soln5_02.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 5-2 Summing integers and calculating the average 2 | import std; 3 | 4 | int main() 5 | { 6 | unsigned int count {}; 7 | long long total {}; 8 | 9 | while (true) 10 | { 11 | std::print("Enter an integer: "); 12 | int n; 13 | std::cin >> n; 14 | total += n; 15 | ++count; 16 | 17 | char yesno {}; 18 | std::print("Do you want to enter another (y/n)? "); 19 | std::cin >> yesno; 20 | 21 | if (std::tolower(yesno) == 'n') 22 | break; 23 | } 24 | 25 | std::println("The total is {}. The average is {:.2f}.", 26 | total, static_cast(total) / count); 27 | } -------------------------------------------------------------------------------- /Exercises/Chapter 05/Soln5_03.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 5-3 Using a do-while loop to count characters 2 | import std; 3 | 4 | int main() 5 | { 6 | unsigned count {}; 7 | char ch {}; 8 | 9 | std::println("Please enter a sequence of characters terminated by '#':"); 10 | 11 | // We have to read at least one character so do-while is best 12 | do 13 | { 14 | std::cin >> ch; 15 | ++count; 16 | } while (ch != '#'); 17 | 18 | // We do not count '#' as a character, so count must be adjusted 19 | --count; 20 | std::println("You entered {} characters (not counting whitespace and the terminal #).", count); 21 | } -------------------------------------------------------------------------------- /Exercises/Chapter 05/Soln5_06.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 5-6. Working with a vector container 2 | import std; 3 | 4 | int main() 5 | { 6 | std::print("What is the largest number I should check? "); 7 | unsigned bound {}; 8 | std::cin >> bound; 9 | 10 | std::vector values; 11 | // Add element values 1 to bound 12 | for (unsigned i {1}; i <= bound; ++i) 13 | values.push_back(i); 14 | 15 | unsigned count {}; // Number of output values 16 | unsigned perline {10}; // Number output perline 17 | for (auto value : values) 18 | { 19 | if (value % 7 == 0 || value % 13 == 0) continue; 20 | std::print("{:8}", value); 21 | if (++count % perline == 0) std::print("\n"); 22 | } 23 | std::print("\n"); 24 | } -------------------------------------------------------------------------------- /Exercises/Chapter 06/Soln6_06.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 6-6. Storing a dynamically allocated vector in a smart pointer 2 | 3 | import std; 4 | 5 | int main() 6 | { 7 | unsigned long long n {}; 8 | std::print("Enter the number of vector elements: "); 9 | std::cin >> n; 10 | auto values{ std::make_unique>(n) }; 11 | 12 | for (unsigned long long i {}; i < n; ++i) // See Soln6_03 for the use of unsigned long long 13 | (*values)[i] = 1.0 / ((i + 1)*(i + 1)); 14 | 15 | double sum {}; 16 | for (auto value : *values) 17 | sum += value; 18 | 19 | std::println("Result is {}", std::sqrt(6.0*sum)); 20 | 21 | // No need to deallocate the memory yourself anymore: the smart pointer takes care of that for you! 22 | } -------------------------------------------------------------------------------- /Exercises/Chapter 08/Soln8_03.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 8_3 Checking the number of arguments entered at the command line. 2 | import std; 3 | 4 | int main(int numArguments, char* arguments[]) 5 | { 6 | switch (numArguments - 1) // arguments[0] is the name of the program! 7 | { 8 | case 2: case 3: case 4: 9 | for (std::size_t i {1}; i < numArguments; ++i) 10 | std::println("Argument {} is {}", i, arguments[i]); 11 | break; 12 | default: 13 | std::println("You entered an incorrect number of arguments.\nPlease enter 2, 3, or 4 arguments."); 14 | } 15 | } -------------------------------------------------------------------------------- /Exercises/Chapter 09/Soln9_05.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 9-5. Using fixed-size std::span<> 2 | import std; 3 | 4 | double average10(std::span data); // Function prototype 5 | 6 | int main() 7 | { 8 | double values[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; 9 | // double values[]{ 1.0, 2.0, 3.0 }; // Only three values!!! 10 | std::println("Average = {}", average10(values)); 11 | } 12 | 13 | // Function to compute an average 14 | double average10(std::span data) 15 | { 16 | double sum{}; // Accumulate total in here 17 | for (double val : data) 18 | sum += val; // Sum array elements 19 | return sum / data.size(); // Return average 20 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_02/words.cppm: -------------------------------------------------------------------------------- 1 | export module words; 2 | 3 | import std; 4 | 5 | export namespace words 6 | { 7 | using Words = std::vector>; 8 | 9 | void sort(Words& words); 10 | void extract_words(Words& words, const std::string& text, const std::string& separators); 11 | void print_words(const Words& words); 12 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_03/words.cppm: -------------------------------------------------------------------------------- 1 | export module words; 2 | 3 | export import words.sorting; 4 | export import words.utils; -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_03/words.sorting.cppm: -------------------------------------------------------------------------------- 1 | export module words.sorting; 2 | 3 | import std; 4 | 5 | export namespace words 6 | { 7 | using Words = std::vector>; 8 | 9 | namespace sorting 10 | { 11 | void sort(Words& words); 12 | } 13 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_03/words.utils.cppm: -------------------------------------------------------------------------------- 1 | export module words.utils; 2 | 3 | import std; 4 | 5 | namespace words 6 | { 7 | export using Words = std::vector>; 8 | } 9 | 10 | export namespace words::utils 11 | { 12 | void extract_words(Words& words, const std::string& text, const std::string& separators); 13 | void print_words(const Words& words); 14 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_04/Soln11_04.cpp: -------------------------------------------------------------------------------- 1 | // Creating a module implementation partition 2 | import std; 3 | import words; 4 | 5 | int main() 6 | { 7 | words::Words the_words; 8 | std::string text; // The string to be sorted 9 | const auto separators{" ,.!?\"\n"}; // Word delimiters 10 | 11 | // Read the string to be processed from the keyboard 12 | std::println("Enter a string terminated by *:"); 13 | getline(std::cin, text, '*'); 14 | 15 | words::extract_words(the_words, text, separators); 16 | if (the_words.empty()) 17 | { 18 | std::println("No words in text."); 19 | return 0; 20 | } 21 | 22 | words::sort(the_words); // Sort the words 23 | words::print_words(the_words); // Output the words 24 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_04/internals.cpp: -------------------------------------------------------------------------------- 1 | module words:internals; 2 | 3 | import words; // For use of words::Words 4 | 5 | void swap(words::Words& words, std::size_t first, std::size_t second) 6 | { 7 | auto temp{ words[first] }; 8 | words[first] = words[second]; 9 | words[second] = temp; 10 | } 11 | 12 | std::size_t max_word_length(const words::Words& words) 13 | { 14 | std::size_t max {}; 15 | for (auto& pword : words) 16 | if (max < pword->length()) max = pword->length(); 17 | return max; 18 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_04/words.cppm: -------------------------------------------------------------------------------- 1 | export module words; 2 | 3 | import std; 4 | 5 | export namespace words 6 | { 7 | using Words = std::vector>; 8 | 9 | void sort(Words& words); 10 | void extract_words(Words& words, const std::string& text, const std::string& separators); 11 | void print_words(const Words& words); 12 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_05/alias.cppm: -------------------------------------------------------------------------------- 1 | export module words:alias; 2 | 3 | import std; 4 | 5 | namespace words 6 | { 7 | export using Words = std::vector>; 8 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_05/internals.cpp: -------------------------------------------------------------------------------- 1 | module words:internals; 2 | 3 | import :alias; // For use of words::Words 4 | 5 | void swap(words::Words& words, std::size_t first, std::size_t second) 6 | { 7 | auto temp{ words[first] }; 8 | words[first] = words[second]; 9 | words[second] = temp; 10 | } 11 | 12 | std::size_t max_word_length(const words::Words& words) 13 | { 14 | std::size_t max {}; 15 | for (auto& pword : words) 16 | if (max < pword->length()) max = pword->length(); 17 | return max; 18 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_05/words.cppm: -------------------------------------------------------------------------------- 1 | export module words; 2 | 3 | export import :alias; 4 | export import :sorting; 5 | export import :utils; -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_06/Soln11_06.cpp: -------------------------------------------------------------------------------- 1 | // Defining alternate names for a namespace 2 | import std; 3 | import words; 4 | 5 | int main() 6 | { 7 | wrds::Words the_words; 8 | std::string text; // The string to be sorted 9 | const auto separators{" ,.!?\"\n"}; // Word delimiters 10 | 11 | // Read the string to be processed from the keyboard 12 | std::println("Enter a string terminated by *:"); 13 | getline(std::cin, text, '*'); 14 | 15 | w::extract_words(the_words, text, separators); 16 | if (the_words.empty()) 17 | { 18 | std::println("No words in text."); 19 | return 0; 20 | } 21 | 22 | wrds::sort(the_words); // Sort the words 23 | w::print_words(the_words); // Output the words 24 | } -------------------------------------------------------------------------------- /Exercises/Chapter 11/Soln11_06/words.cppm: -------------------------------------------------------------------------------- 1 | export module words; 2 | 3 | import std; 4 | 5 | export namespace words 6 | { 7 | using Words = std::vector>; 8 | 9 | void sort(Words& words); 10 | void extract_words(Words& words, const std::string& text, const std::string& separators); 11 | void print_words(const Words& words); 12 | } 13 | 14 | // Technique 1: export a namespace alias 15 | export namespace w = words; 16 | 17 | // Technique 2: export a using namespace directive 18 | namespace wrds 19 | { 20 | export using namespace words; 21 | } 22 | -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_01/Integer.cpp: -------------------------------------------------------------------------------- 1 | module integer; 2 | import std; 3 | 4 | Integer::Integer(int value) : m_value{value} 5 | { 6 | std::println("Object created."); 7 | } 8 | 9 | void Integer::printValue() const 10 | { 11 | std::println("Value is {}.", m_value); 12 | } -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_01/Integer.cppm: -------------------------------------------------------------------------------- 1 | export module integer; 2 | 3 | export class Integer 4 | { 5 | public: 6 | Integer(int value); 7 | int getValue() const { return m_value; } 8 | void setValue(int value) { m_value = value; } 9 | void printValue() const; 10 | 11 | private: 12 | int m_value; 13 | }; 14 | -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_02/Integer.cpp: -------------------------------------------------------------------------------- 1 | module integer; 2 | import std; 3 | 4 | // Constructor 5 | Integer::Integer(int value) 6 | : m_value{ value } 7 | { 8 | std::println("Object created."); 9 | } 10 | 11 | // Copy constructor 12 | Integer::Integer(const Integer& obj) 13 | : m_value{ obj.m_value } 14 | { 15 | std::println("Object created by copy constructor."); 16 | } 17 | 18 | // Compare function with reference parameter 19 | int Integer::compare(const Integer& obj) const 20 | { 21 | if (m_value < obj.m_value) 22 | return -1; 23 | else if (m_value == obj.m_value) 24 | return 0; 25 | else 26 | return 1; 27 | } 28 | 29 | void Integer::printValue() const 30 | { 31 | std::println("Value is {}.", m_value); 32 | } 33 | -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_03/Integer.cppm: -------------------------------------------------------------------------------- 1 | export module integer; 2 | 3 | export class Integer 4 | { 5 | public: 6 | Integer(int value = 0); 7 | Integer(const Integer& obj); 8 | 9 | int getValue() const { return m_value; } 10 | void setValue(int value) { m_value = value; } 11 | 12 | Integer& add(const Integer& obj); 13 | Integer& subtract(const Integer& obj); 14 | Integer& multiply(const Integer& obj); 15 | 16 | int compare(const Integer& obj) const; 17 | 18 | void printValue() const; 19 | 20 | private: 21 | int m_value; 22 | }; 23 | -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_04/Integer.cpp: -------------------------------------------------------------------------------- 1 | module integer; 2 | import std; 3 | 4 | void Integer::printValue() const 5 | { 6 | std::println("Value is {}.", m_value); 7 | } -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_04/Soln12_04.cpp: -------------------------------------------------------------------------------- 1 | // constexpr members... 2 | import std; 3 | import integer; 4 | 5 | int main() 6 | { 7 | // Create the even operands as Integers, 8 | // and use implicit conversions from int for the odd values 9 | constexpr Integer four{4}; // Cannot use four below because constexpr implies const and multiply() is not const... 10 | constexpr Integer six{6}; 11 | constexpr Integer eight{8}; 12 | 13 | // We can calculate 4*5*5*5+6*5*5+7*5+8 as: 14 | // ((4*5+6)*5+7)*5+8 15 | constexpr int result{ Integer{ 4 }.multiply(5).add(six).multiply(5).add(7).multiply(5).add(eight).getValue() }; // Set result object as copy of four 16 | 17 | std::println("Result is {}", result); 18 | } -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_05/Integer.cppm: -------------------------------------------------------------------------------- 1 | export module integer; 2 | 3 | export class Integer 4 | { 5 | public: 6 | Integer(int value = 0); 7 | Integer(const Integer& obj); 8 | 9 | int getValue() const { return m_value; } 10 | void setValue(int value) { m_value = value; } 11 | 12 | void printValue() const; 13 | 14 | friend int compare(const Integer& obj1, const Integer& obj2); // friend compare function 15 | 16 | private: 17 | int m_value; 18 | }; 19 | 20 | // A non-friend function that implements the same function 21 | export int nonFriendCompare(const Integer& obj1, const Integer& obj2); 22 | -------------------------------------------------------------------------------- /Exercises/Chapter 12/Soln12_06/Integer.cppm: -------------------------------------------------------------------------------- 1 | export module integer; 2 | 3 | export class Integer 4 | { 5 | public: 6 | Integer(int value = 0); // Constructor with given value 7 | Integer(const Integer& obj); // Copy constructor 8 | ~Integer(); // Destructor 9 | 10 | int getValue() const { return m_value; } 11 | void setValue(int value) { m_value = value; } 12 | 13 | int compare(const Integer& obj) const; // Compare function with reference parameter 14 | 15 | void printValue() const; 16 | 17 | static void printCount(); 18 | 19 | private: 20 | int m_value; 21 | static inline unsigned int s_count {}; 22 | }; 23 | -------------------------------------------------------------------------------- /Exercises/Chapter 13/Soln13_01/Soln13_01.cpp: -------------------------------------------------------------------------------- 1 | // Implementing the * operator for the Box class to post-multiply by an integer 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | Box box {2, 3, 4}; 8 | std::println("Box is {}", to_string(box)); 9 | unsigned n {3}; 10 | Box newBox{ box * n }; 11 | std::println("After multiplying by {} box is {}", n, to_string(newBox)); 12 | } 13 | -------------------------------------------------------------------------------- /Exercises/Chapter 13/Soln13_02/Soln13_02.cpp: -------------------------------------------------------------------------------- 1 | // Implementing the * operator for the Box class to pre-multiply by a number 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | Box box {2, 3, 4}; 8 | std::println("Box is {}", to_string(box)); 9 | unsigned n {3}; 10 | Box newBox{ n * box }; 11 | std::println("After pre-multiplying by {} box is {}", n, to_string(newBox)); 12 | } 13 | -------------------------------------------------------------------------------- /Exercises/Chapter 13/Soln13_05/Soln13_05.cpp: -------------------------------------------------------------------------------- 1 | // Overloading the >> operator 2 | import std; 3 | import box; 4 | 5 | int main() 6 | { 7 | Box my_box; 8 | std::cin >> my_box; 9 | std::cout << my_box << std::endl; 10 | } 11 | -------------------------------------------------------------------------------- /Exercises/Chapter 13/Soln13_09/PRNG.cppm: -------------------------------------------------------------------------------- 1 | export module PRNG; 2 | import std; 3 | 4 | export class PseudoRandomNumberGenerator 5 | { 6 | public: 7 | PseudoRandomNumberGenerator(int n = 0) 8 | : m_n{ std::abs(n) % 100 } 9 | {} 10 | 11 | // A function call operator (no parameters, return type int) 12 | // Unlike many function call operators, this one alters the state of the object. 13 | int operator()() 14 | { 15 | const int current{ m_n }; 16 | m_n = (m_n * 41 + 7) % 100; // See chapter 12 17 | return current; 18 | } 19 | 20 | private: 21 | int m_n; 22 | }; 23 | -------------------------------------------------------------------------------- /Exercises/Chapter 14/Soln14_01/Soln14_01.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 14-1 Exercising the Animal classes 2 | // The solution shows two options, with the second one being the preferred option. 3 | import animals; 4 | 5 | int main() 6 | { 7 | Lion myLion{"Leo", 400}; 8 | Aardvark myAardvark{"Algernon", 50}; 9 | myLion.who(); 10 | myAardvark.who(); 11 | } -------------------------------------------------------------------------------- /Exercises/Chapter 14/Soln14_02/Soln14_02.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 14-2 The who() function for the base class has the protected access specifier, 2 | // so we ensure the derived classes allow public access to the who() function. 3 | // The solution shows two alternatives, the second one being the preferred option. 4 | 5 | import animals; 6 | 7 | int main() 8 | { 9 | Lion myLion{"Leo", 400}; 10 | Aardvark myAardvark{"Algernon", 50}; 11 | myLion.who(); 12 | myAardvark.who(); 13 | } -------------------------------------------------------------------------------- /Exercises/Chapter 14/Soln14_03/Animals.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 14-3 - Animals.cpp 2 | // Implementations of the Animal class and classes derived from Animal 3 | module animals; 4 | import std; 5 | 6 | // Identify the animal 7 | void Animal::who() const 8 | { 9 | std::println("My name is {} and I weigh {} lbs.", m_name, m_weight); 10 | } 11 | 12 | // Identify the Lion 13 | void Lion::who() const 14 | { 15 | std::print("Rrroarrrr... I am a lion. "); 16 | Animal::who(); // Call base function 17 | } 18 | 19 | // Identify the Aardvark 20 | void Aardvark::who() const 21 | { 22 | Animal::who(); // Call base function 23 | std::println("Oh. And I'm an aardvark."); 24 | } -------------------------------------------------------------------------------- /Exercises/Chapter 14/Soln14_03/Soln14_03.cpp: -------------------------------------------------------------------------------- 1 | // Exercise 14-3 By adding a few lines to the test program, we can see the difference 2 | // between the calls to the base class and derived class who() functions. 3 | 4 | import std; 5 | import animals; 6 | 7 | int main() 8 | { 9 | Lion myLion{"Leo", 400}; 10 | Aardvark myAardvark{"Algernon", 50}; 11 | std::println("Calling derived versions of who():"); 12 | myLion.who(); 13 | myAardvark.who(); 14 | 15 | std::println("\nCalling base versions of who():"); 16 | myLion.Animal::who(); // By qualifying the base class 17 | static_cast(myAardvark).who(); // By casting 18 | } -------------------------------------------------------------------------------- /Exercises/Chapter 15/Soln15_01/Zoo.cpp: -------------------------------------------------------------------------------- 1 | // Implementations of the Zoo class that stores pointers to Animals 2 | module zoo; 3 | import animals; 4 | import std; 5 | 6 | // Constructor from a vector of animals 7 | Zoo::Zoo(const std::vector& animals) 8 | : m_animals{ animals } 9 | {} 10 | 11 | // Add an animal to the zoo 12 | void Zoo::addAnimal(AnimalPtr animal) 13 | { 14 | m_animals.push_back(animal); 15 | } 16 | 17 | // Output the animals and the sound they make 18 | void Zoo::showAnimals() const 19 | { 20 | for (const auto& animal : m_animals) 21 | { 22 | std::println("{} {}", animal->who(), animal->sound()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Exercises/Chapter 15/Soln15_02/Zoo.cpp: -------------------------------------------------------------------------------- 1 | // Implementations of the Zoo class that stores pointers to Animals 2 | module zoo; 3 | import animals; 4 | import std; 5 | 6 | // Constructor from a vector of animals 7 | Zoo::Zoo(const std::vector& animals) 8 | : m_animals{ animals } 9 | {} 10 | 11 | // Add an animal to the zoo 12 | void Zoo::addAnimal(AnimalPtr animal) 13 | { 14 | m_animals.push_back(animal); 15 | } 16 | 17 | // Output the animals and the sound they make 18 | void Zoo::showAnimals() const 19 | { 20 | for (const auto& animal : m_animals) 21 | { 22 | std::println("{} {}", animal->who(), animal->sound()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Exercises/Chapter 15/Soln15_03/Zoo.cpp: -------------------------------------------------------------------------------- 1 | // Implementations of the Zoo class that stores pointers to Animals 2 | module zoo; 3 | import animals; 4 | import std; 5 | 6 | // Constructor from a vector of animals 7 | Zoo::Zoo(const std::vector& animals) 8 | : m_animals{ animals } 9 | {} 10 | 11 | // Add an animal to the zoo 12 | void Zoo::addAnimal(AnimalPtr animal) 13 | { 14 | m_animals.push_back(animal); 15 | } 16 | 17 | // Output the animals and the sound they make 18 | void Zoo::showAnimals() const 19 | { 20 | for (const auto& animal : m_animals) 21 | { 22 | std::println("{} {}", animal->who(), animal->sound()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Exercises/Chapter 15/Soln15_06/Point.cppm: -------------------------------------------------------------------------------- 1 | // A simple class for 2-dimensional points 2 | export module point; 3 | 4 | export class Point final 5 | { 6 | public: 7 | Point(double x, double y) : m_x{x}, m_y{y} {} 8 | 9 | double getX() const { return m_x; } 10 | double getY() const { return m_y; } 11 | 12 | void setX(double x) { m_x = x; } 13 | void setY(double y) { m_y = y; } 14 | 15 | private: 16 | double m_x; 17 | double m_y; 18 | }; 19 | -------------------------------------------------------------------------------- /Exercises/Chapter 16/Exer16_06/Customer.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ customer class 2 | 3 | export module customer; 4 | 5 | import std; 6 | 7 | export class Customer 8 | { 9 | public: 10 | Customer( 11 | std::string_view surname, 12 | std::string_view name, 13 | std::string_view street, 14 | int streetNumber, 15 | std::string_view city 16 | ); 17 | 18 | friend std::string to_string(const Customer& customer); 19 | 20 | private: 21 | std::string m_surname; 22 | std::string m_name; 23 | std::string m_street; 24 | int m_streetNumber; 25 | std::string m_city; 26 | }; 27 | -------------------------------------------------------------------------------- /Exercises/Chapter 16/Exer16_06/DBException.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ exception type 2 | 3 | export module db_exception; 4 | import std; 5 | 6 | export class DatabaseException : public std::runtime_error 7 | { 8 | public: 9 | using std::runtime_error::runtime_error; // Inherit constructor 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /Exercises/Chapter 16/Soln16_01/Curveball.cppm: -------------------------------------------------------------------------------- 1 | // Definition of Curveball exception class 2 | 3 | export module curveball; 4 | import std; 5 | 6 | export class Curveball : public std::exception 7 | { 8 | public: 9 | const char* what() const noexcept override 10 | { 11 | return "Curveball exception"; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /Exercises/Chapter 16/Soln16_02/Curveball.cppm: -------------------------------------------------------------------------------- 1 | // Definition of Curveball exception class 2 | 3 | export module curveball; 4 | import std; 5 | 6 | export class Curveball : public std::exception 7 | { 8 | public: 9 | const char* what() const noexcept override 10 | { 11 | return "Curveball exception"; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /Exercises/Chapter 16/Soln16_05/Curveball.cppm: -------------------------------------------------------------------------------- 1 | // Definition of Curveball exception class 2 | 3 | export module curveball; 4 | import std; 5 | 6 | export class Curveball : public std::exception 7 | { 8 | public: 9 | const char* what() const noexcept override 10 | { 11 | return "Curveball exception"; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /Exercises/Chapter 16/Soln16_06/Customer.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ customer class 2 | 3 | export module customer; 4 | 5 | import std; 6 | 7 | export class Customer 8 | { 9 | public: 10 | Customer( 11 | std::string_view surname, 12 | std::string_view name, 13 | std::string_view street, 14 | int streetNumber, 15 | std::string_view city 16 | ); 17 | 18 | friend std::string to_string(const Customer& customer); 19 | 20 | private: 21 | std::string m_surname; 22 | std::string m_name; 23 | std::string m_street; 24 | int m_streetNumber; 25 | std::string m_city; 26 | }; 27 | -------------------------------------------------------------------------------- /Exercises/Chapter 16/Soln16_06/DBException.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ exception type 2 | 3 | export module db.exception; 4 | import std; 5 | 6 | export class DatabaseException : public std::runtime_error 7 | { 8 | public: 9 | using std::runtime_error::runtime_error; // Inherit constructor 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /Exercises/Chapter 17/Soln17_01/Soln17_01.cpp: -------------------------------------------------------------------------------- 1 | // Adding a push_back() member function and a default constructor to the Array<> 2 | // class template. Using copy-and-swap for a exception-safe push_back(). 3 | import array; 4 | import std; 5 | 6 | int main() 7 | { 8 | const unsigned numElements{ 100 }; 9 | 10 | Array squares; // default construction 11 | for (unsigned i {}; i < numElements; ++i) 12 | squares.push_back(i * i); // push_back() 13 | 14 | std::println("{} squares were added.", squares.getSize()); 15 | std::println("For instance: 13 squared equals {}", squares[13]); 16 | } -------------------------------------------------------------------------------- /Exercises/Chapter 18/Soln18_03/Customer.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ customer class 2 | 3 | export module customer; 4 | 5 | import std; 6 | 7 | export class Customer 8 | { 9 | public: 10 | Customer( 11 | std::string_view surname, 12 | std::string_view name, 13 | std::string_view street, 14 | int streetNumber, 15 | std::string_view city 16 | ); 17 | 18 | friend std::string to_string(const Customer& customer); 19 | 20 | private: 21 | std::string m_surname; 22 | std::string m_name; 23 | std::string m_street; 24 | int m_streetNumber; 25 | std::string m_city; 26 | }; 27 | -------------------------------------------------------------------------------- /Exercises/Chapter 18/Soln18_03/DBException.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ exception type 2 | 3 | export module db.exception; 4 | import std; 5 | 6 | export class DatabaseException : public std::runtime_error 7 | { 8 | public: 9 | using std::runtime_error::runtime_error; // Inherit constructor 10 | }; 11 | -------------------------------------------------------------------------------- /Exercises/Chapter 18/Soln18_04/Customer.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ customer class 2 | 3 | export module customer; 4 | 5 | import std; 6 | 7 | export class Customer 8 | { 9 | public: 10 | Customer( 11 | std::string_view surname, 12 | std::string_view name, 13 | std::string_view street, 14 | int streetNumber, 15 | std::string_view city 16 | ); 17 | 18 | friend std::string to_string(const Customer& customer); 19 | 20 | private: 21 | std::string m_surname; 22 | std::string m_name; 23 | std::string m_street; 24 | int m_streetNumber; 25 | std::string m_city; 26 | }; 27 | -------------------------------------------------------------------------------- /Exercises/Chapter 18/Soln18_04/DBException.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ exception type 2 | 3 | export module db.exception; 4 | 5 | import std; 6 | 7 | export class DatabaseException : public std::runtime_error 8 | { 9 | public: 10 | using std::runtime_error::runtime_error; // Inherit constructor 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /Exercises/Chapter 18/Soln18_05/Customer.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ customer class 2 | 3 | export module customer; 4 | 5 | import std; 6 | 7 | export class Customer 8 | { 9 | public: 10 | Customer( 11 | std::string_view surname, 12 | std::string_view name, 13 | std::string_view street, 14 | int streetNumber, 15 | std::string_view city 16 | ); 17 | 18 | friend std::string to_string(const Customer& customer); 19 | 20 | private: 21 | std::string m_surname; 22 | std::string m_name; 23 | std::string m_street; 24 | int m_streetNumber; 25 | std::string m_city; 26 | }; 27 | -------------------------------------------------------------------------------- /Exercises/Chapter 18/Soln18_05/DBException.cppm: -------------------------------------------------------------------------------- 1 | // A simple C++ exception type 2 | 3 | export module db.exception; 4 | 5 | import std; 6 | 7 | export class DatabaseException : public std::runtime_error 8 | { 9 | public: 10 | using std::runtime_error::runtime_error; // Inherit constructor 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /Exercises/Chapter 19/Soln19_01/Soln19_01.cpp: -------------------------------------------------------------------------------- 1 | // A lambda expression returning the number of vector elements that begin with a given letter. 2 | 3 | import std; 4 | 5 | int main() 6 | { 7 | std::vector words{"apple", "pear", "plum", "orange", "peach", "grape", "greengage"}; 8 | std::println("Words are: {}", words); 9 | 10 | const auto count { 11 | [&words](char letter) 12 | { 13 | std::size_t n {}; 14 | for (auto& word : words) 15 | if (letter == word[0]) ++n; 16 | return n; 17 | } 18 | }; 19 | 20 | char ch {'p'}; 21 | std::println("There are {} words that begin with {}.", count(ch), ch); 22 | ch = 'g'; 23 | std::println("There are {} words that begin with {}.", count(ch), ch); 24 | } -------------------------------------------------------------------------------- /Exercises/Chapter 19/Soln19_03/Sort.cppm: -------------------------------------------------------------------------------- 1 | export module sort; 2 | 3 | // The two algorithms that we are comparing: 4 | export import sort.quick; 5 | export import sort.bubble; 6 | -------------------------------------------------------------------------------- /Exercises/Chapter 19/Soln19_04/Collect.cppm: -------------------------------------------------------------------------------- 1 | export module collect; 2 | 3 | import std; 4 | 5 | export template 6 | std::vector collect(const std::vector& values, Predicate predicate) 7 | { 8 | std::vector result; 9 | 10 | for (auto& value : values) 11 | if (predicate(value)) 12 | result.push_back(value); 13 | 14 | return result; 15 | } 16 | -------------------------------------------------------------------------------- /Exercises/Chapter 19/Soln19_05/DeliveryTruck.cpp: -------------------------------------------------------------------------------- 1 | module delivery_truck; 2 | 3 | DeliveryTruck::DeliveryTruck(Truckload aTruckload) 4 | : m_truckload{ std::move(aTruckload) } // Do not copy! 5 | {} 6 | 7 | void DeliveryTruck::deliverBox(SharedBox box) 8 | { 9 | m_truckload.removeBox(box); 10 | 11 | // Notify all interested parties (aka "observers") that the Box was delivered 12 | for (auto& callback : m_callbacks) 13 | callback(box); 14 | } 15 | 16 | void DeliveryTruck::registerOnDelivered(Callback callback) 17 | { 18 | m_callbacks.push_back(std::move(callback)); // Do not copy! 19 | } -------------------------------------------------------------------------------- /Exercises/Chapter 20/Soln20_07/Soln20_07.cpp: -------------------------------------------------------------------------------- 1 | // Removing all elements that satisfy a certain condition 2 | // while iterating over a container 3 | import std; 4 | 5 | using namespace std::ranges::views; 6 | 7 | int main() 8 | { 9 | const int num_numbers{ 15 }; 10 | 11 | auto numbers{ iota(1, num_numbers + 1) }; 12 | 13 | std::println("The original set of numbers: {:n}", numbers); 14 | 15 | auto odd_numbers{ numbers | filter([](int i) { return i % 2 != 0; }) }; 16 | 17 | std::println("The numbers that were kept: {:n}", odd_numbers); 18 | } -------------------------------------------------------------------------------- /Exercises/Chapter 20/Soln20_15/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() = default; 7 | Box(double length, double width, double height) 8 | : m_length{length}, m_width{width}, m_height{height} {}; 9 | 10 | double volume() const 11 | { 12 | return m_length * m_width * m_height; 13 | } 14 | 15 | double getLength() const { return m_length; } 16 | double getWidth() const { return m_width; } 17 | double getHeight() const { return m_height; } 18 | 19 | private: 20 | double m_length {1.0}; 21 | double m_width {1.0}; 22 | double m_height {1.0}; 23 | }; 24 | -------------------------------------------------------------------------------- /Exercises/Chapter 20/Soln20_15/Soln20_15.cpp: -------------------------------------------------------------------------------- 1 | // Implementing a custom std::formatter<> specialization to format Box objects 2 | import box; 3 | import box.formatter; 4 | import std; 5 | 6 | int main() 7 | { 8 | Box box{ 1, 2, 3 }; 9 | std::println("My new box, {:.2}, is fabulous!", box); 10 | } -------------------------------------------------------------------------------- /Exercises/Chapter 20/Soln20_16/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() = default; 7 | Box(double length, double width, double height) 8 | : m_length{length}, m_width{width}, m_height{height} {}; 9 | 10 | double volume() const 11 | { 12 | return m_length * m_width * m_height; 13 | } 14 | 15 | double getLength() const { return m_length; } 16 | double getWidth() const { return m_width; } 17 | double getHeight() const { return m_height; } 18 | 19 | private: 20 | double m_length {1.0}; 21 | double m_width {1.0}; 22 | double m_height {1.0}; 23 | }; 24 | -------------------------------------------------------------------------------- /Exercises/Chapter 20/Soln20_16/Soln20_16.cpp: -------------------------------------------------------------------------------- 1 | // Implementing a custom std::formatter<> specialization to format Box objects 2 | import std; 3 | import box; 4 | import box.formatter; 5 | 6 | int main() 7 | { 8 | Box box{ 1, 2, 3 }; 9 | std::println("My new box, {:.2}, is fabulous!", box); 10 | std::println("It has these dimensions: {:.2n}", box); 11 | } -------------------------------------------------------------------------------- /Exercises/Chapter 20/Soln20_17/Box.cppm: -------------------------------------------------------------------------------- 1 | export module box; 2 | 3 | export class Box 4 | { 5 | public: 6 | Box() = default; 7 | Box(double length, double width, double height) 8 | : m_length{length}, m_width{width}, m_height{height} {}; 9 | 10 | double volume() const 11 | { 12 | return m_length * m_width * m_height; 13 | } 14 | 15 | double getLength() const { return m_length; } 16 | double getWidth() const { return m_width; } 17 | double getHeight() const { return m_height; } 18 | 19 | private: 20 | double m_length {1.0}; 21 | double m_width {1.0}; 22 | double m_height {1.0}; 23 | }; 24 | -------------------------------------------------------------------------------- /Exercises/Chapter 20/Soln20_17/Soln20_17.cpp: -------------------------------------------------------------------------------- 1 | // Implementing a custom std::formatter<> specialization to format Box objects 2 | import std; 3 | import box; 4 | import box.formatter; 5 | 6 | int main() 7 | { 8 | Box box{ 1, 2, 3 }; 9 | std::println("My new box, {:.2}, is fabulous!", box); 10 | std::println("It has these dimensions: {:.2n}", box); 11 | } -------------------------------------------------------------------------------- /Exercises/README.md: -------------------------------------------------------------------------------- 1 | # Exercise Solutions 2 | 3 | This directory contains the solutions to all exercises of 4 | [*Beginning C++23*](https://www.apress.com/9781484258835) by Ivor Horton and Peter Van Weert (Apress, 2023). 5 | 6 | Consult the [Workarounds](../Workarounds) directory on 7 | how to work around compilation issues with C++23 language and library features 8 | that your compiler may not (fully) [support](https://en.cppreference.com/w/cpp/compiler_support). 9 | -------------------------------------------------------------------------------- /Images/CMakeGui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Images/CMakeGui.png -------------------------------------------------------------------------------- /Images/ConfigureStartupProjects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Images/ConfigureStartupProjects.png -------------------------------------------------------------------------------- /Images/MyExercises.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Images/MyExercises.png -------------------------------------------------------------------------------- /Images/StartupProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Images/StartupProject.png -------------------------------------------------------------------------------- /Images/VisualStudio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/beginning-cpp23/3cd054c74ab2777b5df0e2903b3b9a7c98c3e8bb/Images/VisualStudio.png -------------------------------------------------------------------------------- /Workarounds/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | 7 | -------------------------------------------------------------------------------- /Workarounds/workarounds.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include --------------------------------------------------------------------------------