Immaculate Syntaxical Apotheosis?

I attempting to make my code as neat and clean as possible as I am embarking on A HUGE project. I have many different structs, unions, and functions that need code to be runned in the main function for them to be initialized, but I want this to be neat and pretty so I am trying to do this by having a mechanism set up where I can add code to a queue at the location that the struct/union/function is declared, BUT the hard part which is the essential part to organization is that NO additional code (i.e no adding onto to the initial code required for this mechanism to work) will have to be added onto main for a new member to be added onto the queue. Also, NO boost libraries because i'm anti sadistic-cargo-cult-enthusiastic-style-programming and also because boost libraries add a full 10-to-15 seconds onto the load time which will be unbearable as I have serious ADD and ADHD.
Last edited on
I have many different structs, unions, and functions that need code to be runned in the main for them to be initialized
The main what? The main function or the main thread?
Also, what does it mean for a function or a union to be "initialized"?

a mechanism where I can add code to a queue at the location that the struct/union/function is declared
This is not possible, as such. Type and code definitions cannot execute code by themselves.
It's possible if you're willing to add an extra code generation step to the build process. IMO, though, if your design requires that you do weird things just for initialization, you should fix your design until it no longer has that requirement.

boost libraries add a full 10-to-15 seconds onto the load time
What are you running this on? A broken toaster?
Last edited on
Thank you so much for your response. To answer your questions:
The main function.
THERE MUST BE A WAY! When there's a will, there's a way, and I have a very strong will, so there is a way or I will make there be a way.
I extremely over-hyperbolized. Boost Libraries actualy add only about 3 to 4 seconds onto the load time
Last edited on
Personally, I have written code before that was designed to be easy to maintain. However, I am having a hard time figuring out from your description exactly what you are trying to do.

Are you trying to keep main as clean as possible? That is easy... write a function elsewhere that takes care of the initialization that you need to have done. If you are trying to auto-initialize instances of your "many different structs..." then it really depends on what you are trying to accomplish whether or not you can actually do it. There are other ways to interpret what you have written. Give us an example of what you are trying to do.

My guess is that you want to avoid initializing a huge number of variables in your main method. One tip that may or may not be useful (again... depends on your unspecified intentions) is to make your classes etc... so that they can be initialized using files (such as xml, ini, or other types of text and/or binary files). That way your code stays clean and you make use of a file parser to populate your classes. Keep in mind though that you still have to put the data into the files that get parsed.

This is actually a fairly common practice in the gaming industry. The team then writes tools to make creating the data files easier.
Last edited on
Thank you so much for your helpful and constructive response. Here is an example of the gist of what i'm doing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct {
    char* my_string;       
} mystruct;
add_code_to_main_queue(
    mystruct.my_string = new char[10];
);    //something relating to this


struct {
    char* this_string;       
} other_struct;
add_code_to_main_queue(
    other_struct.this_string = new char[10];
);    //something relating to this

int main( void ) {
    do_main_queue();    //something relating to this which will unravel the main_queue to executing all of the code in the queue
}
Last edited on
Boost Libraries actualy add only about 3 to 4 seconds onto the load time
So you've upgraded from broken toaster to 1980s hardware, have you?

The only way I can see this happening is this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void add_to_initialization_list(std::function<void()> &&);

template <typename T>
struct AutoInitializationInitiator{
    WeirdInitializationInitiator(){
        add_to_initialization_list([](){ T::global_instance.initialize_me(); });
    }
};

#define DECLARE_AUTO_INIT(T) \
    static T global_instance; \
    static AutoInitializationInitiator<T> static_AutoInitializationInitiator;
    void initialize_me()

#define DEFINE_AUTO_INIT(T) \
    T T::global_instance; \
    AutoInitializationInitiator<T> T::static_AutoInitializationInitiator

class SampleClass{
public:
    // Default constructor must be available!
    SampleClass();
    DEFINE_AUTO_INIT(SampleClass);
};

// In .cpp
DEFINE_AUTO_INIT(SampleClass);

void SampleClass::initialize_me(){
    //...
}
Notes:
* Order of initialization is not guaranteed.
* I don't think this is considerably better than just individually adding every object to the initialization list.
* The only reason you appear to want this is because you have a bunch of global objects that you want to initialize. So really you're patching up bad design with more bad design. Is there any reason why you need to have such a large number of globals that automating their initialization makes sense?
Last edited on
So you've decided on a single solution to your problem and want someone to implement it for you?

When you have a personal set of restrictions and want someone to code around the restrictions, you also say how much you're willing to pay them.

Maybe you should describe exactly what the problem is and ask for approaches to tackle it.

Also, this is a C++ forum, but the code you provided is broken C and the C++ new operator.


To do exactly what I think it is that you want, you could use constructors in the struct. Then all you have to do in main() is initialize the object.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct my_string {
public:
  my_string();
  ~my_string();

private:
  char m_my_string[10];
};

my_string::my_string()
: m_my_string(new char[10])
{}

my_string::~my_string()
{
  delete[] m_my_string; // called when my_string goes out of scope
}

int main()
{
  my_string str(); // initialized here
  return 0;
}
Last edited on
What Hydranix said. I myself was going to ask after reading your description if you know ahead of time the size of your char arrays ahead of time because if so, then Hydranix gave the same suggestion I would have. Also, does your initialization queue require filling those structs with data? Implementing the second question is more complicated but for the first question: even if you don't know the size of each instance ahead of time, you can pass a const int in your constructor and replace the '10' in Hydranix's code with that const int variable.

Basically, what you want may be possible (or may not). That depends entirely on your specifications and the understanding of the tools (in C++) that you have at your disposal. People in forums will help you understand the tools you have available but as Hydranix suggested, coming up with a specific implementation; particularly when we don't understand ALL the necessary details of your project is going to be up to you.
da peppester wrote:
1
2
3
4
int main( ) {
    do_main_queue();    // something like this which will unravel the main_queue by 
                                        // executing all of the code in the queue
}


Maybe the OP simply wants something like a container of objects, or even a polymorphic container?

1
2
3
4
5
std::vector<MyClass> MyContainer;
// ... emplace_back  vector with objects 

// It's more code in main, but that is perhaps as tidy as it might get
for (const auto& element : MyContainer) { element.Execute(); } 


In terms of keeping things tidy, consider what happens in a GUI app - like one created with Qt. The main.cpp file calls Application::Execute() and nothing else. All other code is executed elsewhere, never mind the whole application could be arbitrarily large. So the idea is that one can always divide and conquer; this keeps things tidy, organised and logical.

As others have said, how one asks a question is important: An example of the actual real world problem is often the best, IMO. That way, we know exactly what we are dealing with, not some abstract ideas that have lots of potential for confusion :+) Sometimes by describing things in terms of Foo & Bar has the implication of telling how to do it (based on that person's interpretation which may be different to the best way of solving) as opposed to specifying the problem and asking how to solve it. To be fair though, it's easy to get those two ideas mixed up. Having seen the actual problem might lead to a completely different and much better solution.
Thank you so much for your reply. Sorry for the confusion, but I've found the answer to this question.

add_code_to_main.hpp
1
2
3
4
5
6
#define add_code_to_main(unique_identifier,...)\
int __##unique_identifier##_tmp_function_(void) {\
	__VA_ARGS__\
	return 0;\
}\
int __##unique_identifier##_tmp_variable_ = __##unique_identifier##_tmp_function_(); 


Example Usage:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <add_code_to_main.hpp>

using namespace std;


struct {
	char* my_string;       
} mystruct;
add_code_to_main(mystruct,
	mystruct.my_string = new char[127];
);


char* myarray[4];
add_code_to_main(myarray,
		myarray[0] = "Letter a.\n\0";
		myarray[1] = "Letter b.\n\0";
		myarray[2] = "Letter c.\n\0";
		myarray[3] = "Letter d.\n\0";
);

int main( void ) {
	
	int v=0;
	int k=0;
	for( const auto &i : myarray) {
		k=0;
		while ( i[k] != '\0' ) {
			mystruct.my_string[v] = i[k];
			++v;
			++k;
		}
	}
	while (v != 128) {		//zeros-out the rest
		mystruct.my_string[v] = '\0';
		++v;
	}
	
	std::cout << mystruct.my_string;
	
	return 0;
}
Last edited on
I attempting to make my code as neat and clean as possible as I am embarking on A HUGE project.
Sorry for the confusion, but I've found the answer to this question.

Who knew you could add code to main by adding code to main? Let's try the exact same code without your macro:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

struct {
    char* my_string;
} mystruct { new char[127]() };  // zero-initialize

char const * myarray[4] = {
    "Letter a.\n",
    "Letter b.\n",
    "Letter c.\n",
    "Letter d.\n"
};

int main() {

    int v = 0;
    int k = 0;
    for (const auto &i : myarray) {
        k = 0;
        while (i[k] != '\0') {
            mystruct.my_string[v] = i[k];
            ++v;
            ++k;
        }
    }

    std::cout << mystruct.my_string;

    return 0;
}
How completely retarded.
Topic archived. No new replies allowed.