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 %s\n", 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.
-
1Of course they get the constructors called, because you explicitly call them. What's wrong with using the same method as the C version? By the way, this question belongs on StackOverflow.Mr Lister– Mr Lister2012年09月16日 05:55:26 +00:00Commented Sep 16, 2012 at 5:55
-
2He can't use the same method as the C version because the class has a constructor and because the class has private data members. Either one makes the class non-POD.David Hammen– David Hammen2012年09月16日 11:49:50 +00:00Commented Sep 16, 2012 at 11:49
-
Ehm, but with "the same method as the C version" I meant doing it the same way as the C version...Mr Lister– Mr Lister2012年09月16日 19:44:24 +00:00Commented Sep 16, 2012 at 19:44
6 Answers 6
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
-
Except it won't work. He has
const
data members in that class, those members are private, and the class has a non-default constructor. The class is not aggregate, so he can't use an initializer list for it. Not even in C++11.David Hammen– David Hammen2012年09月16日 16:35:14 +00:00Commented Sep 16, 2012 at 16:35
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.
-
Using GDB I can see the constructors being called.gam3– gam32012年09月17日 14:32:17 +00:00Commented Sep 17, 2012 at 14:32
-
Try compiling release with optimizations on. Debugging debug code of course will step into the constructor. Any other debugger would be crap.Thomas Eding– Thomas Eding2012年09月17日 17:46:17 +00:00Commented Sep 17, 2012 at 17:46
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
-
it may work for you... BUT never expect others who suffer from your code to be proud of what you have archived. This will lead to code which is really really hard to debug.Cutton Eye– Cutton Eye2022年08月12日 14:40:55 +00:00Commented Aug 12, 2022 at 14:40
Explore related questions
See similar questions with these tags.