Here's a forum-game-type-thing for ya's.
You know how the C++ language has many different ways of doing the same thing, and that object-oriented programming has the pitfall that it becomes tempting to over-engineer even the simplest task? What I propose we do is that we each take it in turns to contribute to the over-engineering of a simple program by re-writing it. Each person adds one additional layer of abstraction and posts their code here. Then the next person engineers it further by adding an extra layer of abstraction.
You could say that adding each additional layer of abstraction to the C++ code is like zooming in on an image that becomes more detailed the more you zoom - a bit like a fractal - hence the name C++ Fractal.
The program I've written below is a simple program to verify that 1+1 does indeed equal 2.
Note that the code I've given is purely in C. There is no obligation for the next person to switch over to C++, but sooner or later, the switch to C++ is going to occur.
AE.
| 1 | #include <stdio.h> |
| 2 | |
| 3 | class Main |
| 4 | { |
| 5 | public: |
| 6 | int run(int argc, char *argv[]) |
| 7 | { |
| 8 | if(1+1==2) |
| 9 | { |
| 10 | printf("Mathematics appears to be in order."); |
| 11 | } |
| 12 | else |
| 13 | { |
| 14 | printf{"Oh dear, mathematics is falling apart."}; |
| 15 | } |
| 16 | } |
| 17 | }; |
| 18 | |
| 19 | int main(int argc, char *argv[]) |
| 20 | { |
| 21 | Main obj; |
| 22 | return obj.run(argc, argv); |
| 23 | } |
Gimmie a minute...
[append]
| 1 | #include <stdio.h> |
| 2 | |
| 3 | class Main |
| 4 | { |
| 5 | public: |
| 6 | enum Message { |
| 7 | MathSuccess, |
| 8 | MathFailure, |
| 9 | }; |
| 10 | void printMessage(Message message) |
| 11 | { |
| 12 | switch(message) |
| 13 | { |
| 14 | case MathSuccess: |
| 15 | printf("Mathematics appears to be in order."); |
| 16 | break; |
| 17 | case MathFailure: |
| 18 | printf("Oh dear, mathematics is falling apart."); |
| 19 | break; |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | int run(int argc, char *argv[]) |
| 24 | { |
| 25 | if(1+1==2) |
| 26 | { |
| 27 | printMessage(MathSuccess); |
| 28 | } |
| 29 | else |
| 30 | { |
| 31 | printMessage(MathFailure); |
| 32 | } |
| 33 | } |
| 34 | }; |
| 35 | |
| 36 | int main(int argc, char *argv[]) |
| 37 | { |
| 38 | Main obj; |
| 39 | return obj.run(argc, argv); |
| 40 | } |
[append]
Nice. 1 post every 10 minutes
| 1 | template <class T, T a, T b, T c> |
| 2 | class SumStatus |
| 3 | { |
| 4 | public: |
| 5 | enum Result |
| 6 | { |
| 7 | Success, |
| 8 | Failure, |
| 9 | }; |
| 10 | |
| 11 | Result getResult() |
| 12 | { |
| 13 | if (a + b == c) |
| 14 | { |
| 15 | return Success; |
| 16 | } |
| 17 | else |
| 18 | { |
| 19 | return Failure; |
| 20 | } |
| 21 | } |
| 22 | }; |
| 23 | |
| 24 | class Main |
| 25 | { |
| 26 | public: |
| 27 | enum Message |
| 28 | { |
| 29 | MathSuccess, |
| 30 | MathFailure, |
| 31 | }; |
| 32 | |
| 33 | void printMessage(Message message) |
| 34 | { |
| 35 | switch(message) |
| 36 | { |
| 37 | case MathSuccess: |
| 38 | printf("Mathematics appears to be in order."); |
| 39 | break; |
| 40 | case MathFailure: |
| 41 | printf("Oh dear, mathematics is falling apart."); |
| 42 | break; |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | int run(int argc, char *argv[]) |
| 47 | { |
| 48 | SumStatus<int,1,1,2> MathStatus; |
| 49 | switch (MathStatus.getResult()) |
| 50 | { |
| 51 | case Sum::Sucess: |
| 52 | printMessage(MathSuccess); |
| 53 | break; |
| 54 | case Sum::Failure: |
| 55 | printMessage(MathFailure); |
| 56 | break; |
| 57 | } |
| 58 | } |
| 59 | }; |
| 60 | |
| 61 | int main(int argc, char *argv[]) |
| 62 | { |
| 63 | Main obj; |
| 64 | return obj.run(argc, argv); |
| 65 | } |
In your template class you have your enum defined ast Result yet you are returning a Status. Just thought I'd point out the bug
Bridge Pattern:
Main.h
class MainImpl; class Main { private: MainImpl* impl; Main& operator=(const Main&); Main(const Main&); public: Main(); ~Main(); int run(int argc, char *argv[]); };
MainImpl.cpp
| 1 | #include "Main.h" |
| 2 | #include <cstdio> |
| 3 | |
| 4 | using std::printf; |
| 5 | |
| 6 | template <class T, T a, T b, T c> |
| 7 | class SumStatus |
| 8 | { |
| 9 | public: |
| 10 | enum Result |
| 11 | { |
| 12 | Success, |
| 13 | Failure, |
| 14 | }; |
| 15 | |
| 16 | Result getResult() |
| 17 | { |
| 18 | if (a + b == c) |
| 19 | { |
| 20 | return Success; |
| 21 | } |
| 22 | else |
| 23 | { |
| 24 | return Failure; |
| 25 | } |
| 26 | } |
| 27 | }; |
| 28 | |
| 29 | |
| 30 | class MainImpl |
| 31 | { |
| 32 | public: |
| 33 | enum Message |
| 34 | { |
| 35 | MathSuccess, |
| 36 | MathFailure, |
| 37 | }; |
| 38 | |
| 39 | void printMessage(Message message) |
| 40 | { |
| 41 | switch(message) |
| 42 | { |
| 43 | case MathSuccess: |
| 44 | printf("Mathematics appears to be in order."); |
| 45 | break; |
| 46 | case MathFailure: |
| 47 | printf("Oh dear, mathematics is falling apart."); |
| 48 | break; |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | int run(int argc, char *argv[]) |
| 53 | { |
| 54 | SumStatus<int,1,1,2> MathStatus; |
| 55 | switch (MathStatus.getResult()) |
| 56 | { |
| 57 | case Sum::Sucess: |
| 58 | printMessage(MathSuccess); |
| 59 | break; |
| 60 | case Sum::Failure: |
| 61 | printMessage(MathFailure); |
| 62 | break; |
| 63 | } |
| 64 | } |
| 65 | }; |
| 66 | |
| 67 | Main::Main() |
| 68 | { |
| 69 | impl = new MainImpl; |
| 70 | } |
| 71 | |
| 72 | Main::~Main() |
| 73 | { |
| 74 | delete impl; |
| 75 | } |
| 76 | |
| 77 | int Main::run(int argc, char *argv[]) |
| 78 | { |
| 79 | return impl->run(); |
| 80 | } |
main.cpp
#include "Main.h" int main(int argc, char *argv[]) { Main obj; return obj.run(argc, argv); }
EDIT:
Fixed the bug Steve Terry pointed out
- OutputDevice (derived classes)
- Made code compilable (;)) and fixed indentation
- Unfortunately I had to convert Steve's template to an ordinary class with constructor in order to compile the code. 
main.cpp:
#include "Main.h" int main(int argc, char *argv[]) { Main obj; return obj.run(argc, argv); }
Main.h:
| 1 | #ifndef _MAIN_H_ |
| 2 | #define _MAIN_H_ |
| 3 | |
| 4 | class MainImpl; |
| 5 | class Main |
| 6 | { |
| 7 | private: |
| 8 | MainImpl* impl; |
| 9 | Main& operator=(const Main&); |
| 10 | Main(const Main&); |
| 11 | public: |
| 12 | Main(); |
| 13 | ~Main(); |
| 14 | int run(int argc, char *argv[]); |
| 15 | }; |
| 16 | |
| 17 | #endif |
MainImpl.cpp:
| 1 | #include "Main.h" |
| 2 | #include "OutputDevice.h" |
| 3 | |
| 4 | class SumStatus |
| 5 | { |
| 6 | private: |
| 7 | int a, b, c; |
| 8 | public: |
| 9 | SumStatus(int a, int b, int c) : a(a), b(b), c(c) {} |
| 10 | |
| 11 | enum Result |
| 12 | { |
| 13 | Success, |
| 14 | Failure, |
| 15 | }; |
| 16 | |
| 17 | Result getResult() |
| 18 | { |
| 19 | if (a + b == c) |
| 20 | { |
| 21 | return Success; |
| 22 | } |
| 23 | else |
| 24 | { |
| 25 | return Failure; |
| 26 | } |
| 27 | } |
| 28 | }; |
| 29 | |
| 30 | |
| 31 | class MainImpl |
| 32 | { |
| 33 | public: |
| 34 | enum Message |
| 35 | { |
| 36 | MathSuccess, |
| 37 | MathFailure, |
| 38 | }; |
| 39 | |
| 40 | void printMessage(OutputDevice* od, Message message) |
| 41 | { |
| 42 | switch(message) |
| 43 | { |
| 44 | case MathSuccess: |
| 45 | od->output("Mathematics appears to be in order."); |
| 46 | break; |
| 47 | case MathFailure: |
| 48 | od->output("Oh dear, mathematics is falling apart."); |
| 49 | break; |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | int run(int argc, char *argv[]) |
| 54 | { |
| 55 | SumStatus MathStatus(1, 1, 2); |
| 56 | OutputDevice* od = new ConsoleOutputDevice; |
| 57 | |
| 58 | switch (MathStatus.getResult()) |
| 59 | { |
| 60 | case SumStatus::Success: |
| 61 | printMessage(od, MathSuccess); |
| 62 | break; |
| 63 | case SumStatus::Failure: |
| 64 | printMessage(od, MathFailure); |
| 65 | break; |
| 66 | } |
| 67 | |
| 68 | delete od; |
| 69 | } |
| 70 | }; |
| 71 | |
| 72 | Main::Main() |
| 73 | { |
| 74 | impl = new MainImpl; |
| 75 | } |
| 76 | |
| 77 | Main::~Main() |
| 78 | { |
| 79 | delete impl; |
| 80 | } |
| 81 | |
| 82 | int Main::run(int argc, char *argv[]) |
| 83 | { |
| 84 | return impl->run(argc, argv); |
| 85 | } |
OutputDevice.h:
| 1 | #ifndef _OUTPUTDEVICE_H_ |
| 2 | #define _OUTPUTDEVICE_H_ |
| 3 | |
| 4 | #include <iostream> |
| 5 | #include <string> |
| 6 | |
| 7 | class OutputDevice |
| 8 | { |
| 9 | public: |
| 10 | virtual void output(std::string str) = 0; |
| 11 | }; |
| 12 | |
| 13 | class ConsoleOutputDevice : public OutputDevice |
| 14 | { |
| 15 | public: |
| 16 | virtual void output(std::string str) |
| 17 | { |
| 18 | std::cout << str << std::endl; |
| 19 | } |
| 20 | }; |
| 21 | |
| 22 | #endif |
[EDIT]
Sorry, forgot the OutputDevice.h!
[EDIT]
I also attached the files now.
Used a policy (templates again):
Status.h:
| 1 | class StatusPolicy |
| 2 | { |
| 3 | public: |
| 4 | enum Result |
| 5 | { |
| 6 | Success, |
| 7 | Failure |
| 8 | } |
| 9 | }; |
| 10 | |
| 11 | class SumStatusPolicy : public StatusPolicy |
| 12 | { |
| 13 | public: |
| 14 | Result operator()(int a, int b, int c) |
| 15 | { |
| 16 | if (a + b == c) |
| 17 | { |
| 18 | return Success; |
| 19 | } |
| 20 | else |
| 21 | { |
| 22 | return Failure; |
| 23 | } |
| 24 | } |
| 25 | }; |
| 26 | |
| 27 | template< class Policy > |
| 28 | class Status |
| 29 | { |
| 30 | private: |
| 31 | int a, b, c; |
| 32 | Policy policy; |
| 33 | public: |
| 34 | SumStatus(int a, int b, int c) : a(a), b(b), c(c) {} |
| 35 | |
| 36 | Policy::Result getResult() |
| 37 | { |
| 38 | return policy(a, b, c); |
| 39 | } |
| 40 | }; |
| 41 | |
| 42 | typedef Status< SumStatusPolicy > SumStatus; |
MainImpl.cpp:
| 1 | #include "Main.h" |
| 2 | #include "OutputDevice.h" |
| 3 | #include "Status.h" |
| 4 | |
| 5 | class MainImpl |
| 6 | { |
| 7 | public: |
| 8 | enum Message |
| 9 | { |
| 10 | MathSuccess, |
| 11 | MathFailure, |
| 12 | }; |
| 13 | |
| 14 | void printMessage(OutputDevice* od, Message message) |
| 15 | { |
| 16 | switch(message) |
| 17 | { |
| 18 | case MathSuccess: |
| 19 | od->output("Mathematics appears to be in order."); |
| 20 | break; |
| 21 | case MathFailure: |
| 22 | od->output("Oh dear, mathematics is falling apart."); |
| 23 | break; |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | int run(int argc, char *argv[]) |
| 28 | { |
| 29 | SumStatus MathStatus(1, 1, 2); |
| 30 | OutputDevice* od = new ConsoleOutputDevice; |
| 31 | |
| 32 | switch (MathStatus.getResult()) |
| 33 | { |
| 34 | case SumStatus::Success: |
| 35 | printMessage(od, MathSuccess); |
| 36 | break; |
| 37 | case SumStatus::Failure: |
| 38 | printMessage(od, MathFailure); |
| 39 | break; |
| 40 | } |
| 41 | |
| 42 | delete od; |
| 43 | return 0; |
| 44 | } |
| 45 | }; |
| 46 | |
| 47 | Main::Main() |
| 48 | { |
| 49 | impl = new MainImpl; |
| 50 | } |
| 51 | |
| 52 | Main::~Main() |
| 53 | { |
| 54 | delete impl; |
| 55 | } |
| 56 | |
| 57 | int Main::run(int argc, char *argv[]) |
| 58 | { |
| 59 | return impl->run(argc, argv); |
| 60 | } |
Warning: As I'm not on a computer with a C++ compiler, I couldn't test it, so it might be that it doesn't even compile.
The rest of the files were unchanged.
This will become something like skynet eventually
In your template class you have your enum defined ast Result yet you are returning a Status. Just thought I'd point out the bug
Oops. I didn't compile.
Don't worry about it, I don't think that printf{"Oh dear, mathematics is falling apart."}; from the original post is valid C either.
Marcello
Ah the joys of over engineering.
It's amazing how bloated a simple program can be in C++. Why don't we switch to Java, to give a better illusion of bloat and slowness?
Don't worry about it, I don't think that printf{"Oh dear, mathematics is falling apart."}; from the original post is valid C either.
It would work if the C code was interpreted instead of compiled.