I am writing some code that has a very large number of reasonably simple objects and I would like them the be created at compile time. I would think that a compiler would be able to do this, but I have not been able to figure out how.
In C I could do the the following:
#include <stdio.h>
typedef struct data_s {
int a;
int b;
char *c;
} info;
info list[] = {
1, 2, "a",
3, 4, "b",
};
main()
{
int i;
for (i = 0; i < sizeof(list)/sizeof(*list); i++) {
printf("%d %sn", i, list[i].c);
}
}
Using #C++* each object has it constructor called rather than just being layed out in memory.
#include <iostream>
using std::cout;
using std::endl;
class Info {
const int a;
const int b;
const char *c;
public:
Info(const int, const int, const char *);
const int get_a() { return a; };
const int get_b() { return b; };
const char *get_c() const { return c; };
};
Info::Info(const int a, const int b, const char *c) : a(a), b(b), c(c) {};
Info list[] = {
Info(1, 2, "a"),
Info(3, 4, "b"),
};
main()
{
for (int i = 0; i < sizeof(list)/sizeof(*list); i++) {
cout << i << " " << list[i].get_c() << endl;
}
}
I just don’t see what information is not available for the compiler to completely instantiate these objects at compile time, so I assume I am missing something.
3
In C++11 you can use a constexpr
constructor like this:
class Info {
const int a;
const int b;
const char *c;
public:
constexpr Info(const int, const int, const char *);
const int get_a() { return a; }
const int get_b() { return b; }
const char *get_c() const { return c; }
};
constexpr Info::Info(const int a, const int b, const char *c) : a(a), b(b), c(c) {}
constexpr Info list[] = {
Info(1, 2, "a"),
Info(3, 4, "b"),
};
GCC 4.7.1 in C++0x mode supports constexpr constructors at compile time, and the above code works as desired, with no calls to the Info constructor in the generated code.
Note that the compiler is not required to do full construction at compile time – in principle it could defer the construction to runtime.
If you want all that extra stuff in there, fine – you’ll have to instantiate them explicitly.
But there’s nothing stopping you using the C way for your objects, just make and treat them as POC structs. C++ is that backwardly compatible. Alternatively, place a struct inside your class as a member variable and instantiate that.
With C++11 you can use initializer lists to construct your object, as per this SO answer
1
You’re hosed. The problems are those const
private data members and the constructor. These makes your class a non-aggregate class. The only way to construct an Info
object is by calling the constructor, and the compiler doesn’t do that.
Who says the compiler isn’t doing exactly what you want? In the code shown, a compliant compiler may compile your List
code to the same assembly as the C code.
2
This probably isn’t going to help you very much, but I’d suggest that you look into template meta programming. 🙂
You can’t really create them at compile time, but you can trick the compiler into specifying the creation of pretty complex data structures by using macros to store information, and then using multiple different definitions of the macro to deposit information as needed.
For example, you can have a macro structure like
in a header file “header.h”:
foo(x,1)
foo(y,2)
then in one place
#define foo(a,b) a = b;
#include "header.h"
#undef foo
and in another place
#define foo(a,b) #a,
char *name = {
#include "header.h"
};
#undef foo
and so on
1