Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » What did I just do?

This thread is locked; no one can reply to it. rss feed Print
What did I just do?
Mark Oates
Member #1,146
March 2001
avatar

Working on my project that has this:

class vec2d
{
public:
   float x;
   float y;
   vec2d(float x, float y) : x(x), y(y) {}
};

...and just on a whim I tried this:

void foo()
{
   vec2d m = {0.0, 0.0};  // <--- ??!!
   std::cout << m.x << ',' << m.y << std::endl;
}

And it worked!

I have no idea what I just did! :o

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

torhu
Member #2,727
September 2002
avatar

It's C++11's new "initializer list" feature. It's not useful in your case, but it also works in cases like this:

std::vector<int> v{1, 2, 3};

;D

APPEND:
What you should have done is just this, but either one works:

vec2d m(0, 0);

The only difference is that my version might be faster, I don't know if the semantics of this feature are that it acts like a temporary object of the type being initialized, or if it just supplies arguments to the constructor on the left hand side.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

C has had static struct initialization for a while now.

exgui.c#SelectExpand
186/* here it comes - the big bad ugly DIALOG array for our main dialog */ 187DIALOG the_dialog[] = 188{ 189 /* (dialog proc) (x) (y) (w) (h) (fg)(bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ 190 191 /* this element just clears the screen, therefore it should come before the others */ 192 { d_clear_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, 193 194 /* these just display text, either left aligned, centered, or right aligned */ 195 { d_text_proc, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, "d_text_proc", NULL, NULL }, 196 { d_ctext_proc, 318, 20, 0, 0, 0, 0, 0, 0, 0, 0, "d_ctext_proc", NULL, NULL }, 197 { d_rtext_proc, 636, 20, 0, 0, 0, 0, 0, 0, 0, 0, "d_rtext_proc", NULL, NULL }, 198 199 /* lots of descriptive text elements */ 200 { d_text_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "d_menu_proc->", NULL, NULL }, 201 { d_text_proc, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, "d_button_proc->", NULL, NULL }, 202 { d_text_proc, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, "d_check_proc->", NULL, NULL }, 203 { d_text_proc, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, "d_radio_proc->", NULL, NULL }, 204 { d_text_proc, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, "d_edit_proc->", NULL, NULL }, 205 { d_text_proc, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, "d_list_proc->", NULL, NULL }, 206 { d_text_proc, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, "d_text_list_proc->", NULL, NULL }, 207 { d_text_proc, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0, "d_textbox_proc->", NULL, NULL }, 208 { d_text_proc, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, "d_slider_proc->", NULL, NULL }, 209 { d_text_proc, 0, 330, 0, 0, 0, 0, 0, 0, 0, 0, "d_box_proc->", NULL, NULL }, 210 { d_text_proc, 0, 360, 0, 0, 0, 0, 0, 0, 0, 0, "d_shadow_box_proc->", NULL, NULL }, 211 { d_text_proc, 0, 390, 0, 0, 0, 0, 0, 0, 0, 0, "d_keyboard_proc. Press F1 to see me trigger the about box.", NULL, NULL }, 212 { d_text_proc, 0, 410, 0, 0, 0, 0, 0, 0, 0, 0, "d_clear_proc. I draw the white background.", NULL, NULL }, 213 { d_text_proc, 0, 430, 0, 0, 0, 0, 0, 0, 0, 0, "d_yield_proc. I make us play nice with the OS scheduler.", NULL, NULL }, 214 { d_rtext_proc, 636, 40, 0, 0, 0, 0, 0, 0, 0, 0, "<-d_bitmap_proc", NULL, NULL }, 215 { d_rtext_proc, 636, 80, 0, 0, 0, 0, 0, 0, 0, 0, "<-d_icon_proc", NULL, NULL }, 216 217 /* a menu bar - note how it auto-calculates its dimension if they are not given */ 218 { d_menu_proc, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, the_menu, NULL, NULL }, 219 220 /* some more GUI elements, all of which require you to specify their dimensions */ 221 { d_button_proc, 160, 40, 160, 20, 0, 0, 't', 0, 0, 0, "&Toggle Me!", NULL, NULL }, 222 { d_check_proc, 160, 70, 160, 20, 0, 0, 'c', 0, 0, 0, "&Check Me!", NULL, NULL }, 223 { d_radio_proc, 160, 100, 160, 19, 0, 0, 's', 0, 0, 0, "&Select Me!", NULL, NULL }, 224 { d_radio_proc, 320, 100, 160, 19, 0, 0, 'o', 0, 0, 0, "&Or Me!", NULL, NULL }, 225 { d_edit_proc, 160, 130, 160, 8, 0, 0, 0, 0, LEN, 0, the_string, NULL, NULL }, 226 { d_list_proc, 160, 150, 160, 44, 0, 0, 0, 0, 0, 0, (void *)listbox_getter, sel, NULL }, 227 { d_text_list_proc, 160, 200, 160, 44, 0, 0, 0, 0, 0, 0, (void *)listbox_getter, NULL, NULL }, 228 { d_textbox_proc, 160, 250, 160, 48, 0, 0, 0, 0, 0, 0, (void *)the_text, NULL, NULL }, 229 { d_slider_proc, 160, 300, 160, 12, 0, 0, 0, 0, 100, 0, NULL, NULL, NULL }, 230 { d_box_proc, 160, 330, 160, 20, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, 231 { d_shadow_box_proc, 160, 360, 160, 20, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, 232 233 /* note how we don't fill in the dp field yet, because we first need to load the bitmap */ 234 { d_bitmap_proc, 480, 40, 30, 30, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, 235 { d_icon_proc, 480, 80, 30, 30, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, 236 237 /* the quit and info buttons use our customized dialog procedure, using dp3 as callback */ 238 { my_button_proc, 0, 450, 160, 20, 0, 0, 'q', D_EXIT, 0, 0, "&Quit", NULL, (void *)quit }, 239 { my_button_proc, 400, 150, 160, 20, 0, 0, 'i', D_EXIT, 0, 0, "&Info", NULL, (void *)info1 }, 240 { my_button_proc, 400, 200, 160, 20, 0, 0, 'n', D_EXIT, 0, 0, "I&nfo", NULL, (void *)info2 }, 241 { my_button_proc, 400, 300, 160, 20, 0, 0, 'f', D_EXIT, 0, 0, "In&fo", NULL, (void *)info3 }, 242 243 /* the next two elements don't draw anything */ 244 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *)about, NULL, NULL }, 245 { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, 246 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } 247};

Look familiar now?

bamccaig
Member #7,536
July 2006
avatar

SiegeLord
Member #7,827
October 2006
avatar

The best bit is that you can do this:

std::vector<vec2d> vec;
vec.push_back({1, 2});

Even C can't do this. This is one of my favorite C++11 features.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

GullRaDriel
Member #3,861
September 2003
avatar

What ? I think I could pull it easily using a variadic macro.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

bamccaig
Member #7,536
July 2006
avatar

bamccaig said:

^ I'm inclined to blame it on C. What if you make x and y private/protected? Does it compile then? ???

For reference, no it does not. So definitely it's just initializing members in order, C-style. Which in hindsight explains why torhu said the constructor was likely faster. I think that's assuming it's guaranteed to run anyway, though since the only defined constructor requires arguments I'd be inclined to guess that it doesn't...

Audric
Member #907
January 2001

I tested, in C you can pass a "literal struct" as a function argument, as long as you cast it :

#SelectExpand
1typedef struct { 2 int x; 3 int y; 4} elem; 5 6void dostuff(elem e) 7{ 8 printf("%d %d\n", e.x, e.y); 9} 10 11int main() 12{ 13 elem e12 = {1, 2}; 14 dostuff(e12); 15 dostuff((elem){3,4}); 16 return 0; 17}

edit: actually it's called a compound literal
It seems to be C99, as well as a GCC-ism in C90
http://stackoverflow.com/questions/10743804/c90-compound-literals

relpatseht
Member #5,034
September 2004
avatar

In C you can do this:

typedef struct vec2d
{
    float x, y;
} vec2d;

vec2d foo = { y: 2.5f, x: 1.5f };
printf("%f %f", foo.x, foo.y); // 1.5 2.5

Sorely missed in C++.

torhu
Member #2,727
September 2002
avatar

bamccaig said:

^ I'm inclined to blame it on C. What if you make x and y private/protected? Does it compile then? ???

I tried with GCC 4.8.1, it doesn't matter if they are private or not. Use the second public: instead to make x and y private.

class vec2d
{
public:
   float x;
   float y;
//public:
   vec2d(float x, float y) : x(x), y(y) {}
};


int main()
{
   vec2d m = {0.0, 0.0};
}

In both cases, this happens:

D:\prog\test>g++ -o test -std=gnu++03 test.cpp
test.cpp: In function 'int main()':
test.cpp:15:23: error: in C++98 'm' must be initialized by constructor, not by '{...}'
    vec2d m = {0.0, 0.0};
                       ^

D:\prog\test>g++ -o test -std=gnu++11 test.cpp

bamccaig
Member #7,536
July 2006
avatar

torhu
Member #2,727
September 2002
avatar

Private is the default for classes ;)

bamccaig
Member #7,536
July 2006
avatar

torhu
Member #2,727
September 2002
avatar

torhu said:

Use the second public: instead to make x and y private.

:-*

But why not just try it yourself?

bamccaig
Member #7,536
July 2006
avatar

Oh. Why the Hell not just write this:

class vec2d
{
public:
   vec2d(float x, float y) : x(x), y(y) {}
//private:
   float x;
   float y;
};

int main()
{
   vec2d m = {0.0, 0.0};
}

It's much more obvious what you're trying to do then. :P

But yes, now I see what you're saying.

Append:

bamccaig said:

For reference, no it does not. So definitely it's just initializing members in order, C-style. Which in hindsight explains why torhu said the constructor was likely faster. I think that's assuming it's guaranteed to run anyway, though since the only defined constructor requires arguments I'd be inclined to guess that it doesn't... For reference, no it does not. So definitely it's just initializing members in order, C-style. Which in hindsight explains why torhu said the constructor was likely faster. I think that's assuming it's guaranteed to run anyway, though since the only defined constructor requires arguments I'd be inclined to guess that it doesn't...

torhu
Member #2,727
September 2002
avatar

Because in reality I just moved public: up and down with editor commands when testing ;D

But anyway, C++11 is nice.

Go to: