C++ Fractal
Andrei Ellman

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.

#include <stdio.h>

int main()
{
   if(1+1==2)
   {
      printf("Mathematics appears to be in order.");
   }
   else
   {
      printf{"Oh dear, mathematics is falling apart."};
   }
}

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.

Billybob
1#include <stdio.h>
2 
3class Main
4{
5public:
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 
19int main(int argc, char *argv[])
20{
21 Main obj;
22 return obj.run(argc, argv);
23}

CGamesPlay

Gimmie a minute...

[append]

1#include <stdio.h>
2 
3class Main
4{
5public:
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 
36int main(int argc, char *argv[])
37{
38 Main obj;
39 return obj.run(argc, argv);
40}

[append]
Nice. 1 post every 10 minutes :)

Steve++
1template <class T, T a, T b, T c>
2class SumStatus
3{
4public:
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 
24class Main
25{
26public:
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 
61int main(int argc, char *argv[])
62{
63 Main obj;
64 return obj.run(argc, argv);
65}

Steve Terry

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 :P

Carrus85

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 
4using std::printf;
5 
6template <class T, T a, T b, T c>
7class SumStatus
8{
9public:
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 
30class MainImpl
31{
32public:
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 
67Main::Main()
68{
69 impl = new MainImpl;
70}
71 
72Main::~Main()
73{
74 delete impl;
75}
76 
77int 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

Michael Faerber

- 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 
4class MainImpl;
5class 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 
4class SumStatus
5{
6private:
7 int a, b, c;
8public:
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 
31class MainImpl
32{
33public:
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 
72Main::Main()
73{
74 impl = new MainImpl;
75}
76 
77Main::~Main()
78{
79 delete impl;
80}
81 
82int 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 
7class OutputDevice
8{
9public:
10 virtual void output(std::string str) = 0;
11};
12 
13class ConsoleOutputDevice : public OutputDevice
14{
15public:
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.

Indeterminatus

Used a policy (templates again):

Status.h:

1class StatusPolicy
2{
3public:
4 enum Result
5 {
6 Success,
7 Failure
8 }
9};
10 
11class SumStatusPolicy : public StatusPolicy
12{
13public:
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 
27template< class Policy >
28class Status
29{
30private:
31 int a, b, c;
32 Policy policy;
33public:
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 
42typedef Status< SumStatusPolicy > SumStatus;

MainImpl.cpp:

1#include "Main.h"
2#include "OutputDevice.h"
3#include "Status.h"
4 
5class MainImpl
6{
7public:
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 
47Main::Main()
48{
49 impl = new MainImpl;
50}
51 
52Main::~Main()
53{
54 delete impl;
55}
56 
57int 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.

Ariesnl

This will become something like skynet eventually ;D

Steve++
Quote:

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 :P

Oops. I didn't compile.

Marcello

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

Thomas Fjellstrom

Ah the joys of over engineering.

BAF

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? ;)

Simon Parzer
Quote:

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.

Thread #587217. Printed from Allegro.cc