Jump to content
  • Advertisement
Sign in to follow this  
Lode

Why does this work?

This topic is 4491 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have this code here, and to my surprise it worked!
#include <string>
#include <iostream>

template<typename T>
struct Damage
{
    T d[12];
};

Damage<std::string> damageNames  = {"None", "", "Blunt", "Sharp", "Magic", "Fire", "Water", "Earth", "Air", "Cold", "Electric", "Poison"};



int main()
{
    std::cout<<damageNames.d[5];
}


It outputs "Fire" for me. I'd like to know: -Why does it work? -Is it supposed to work according to the C++ standard? -Is it safe? -Is the {"None", "", "Blunt", "Sharp", "Magic", "Fire", "Water", "Earth", "Air", "Cold", "Electric", "Poison"} called an initializer list? Thanks!

Share this post


Link to post
Share on other sites
Advertisement
Your struct is considered an aggregate, as it has no user declared constructors, no private or protected non static member variables, no virtual functions and no base classes. Aggregates can be initialized with an aggregate initializer list, which is the brace enclosed list. Each item in the list is applied as an argument for a constructor for the corresponding element in the aggregate. In the case of an array member variable of an aggregate each successive element in the aggregate intializer list is applied to successive array elements.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
thats a fully valid way to assign values to an array.

and ofcourse it works with any type aslong as that type is specified when the struct is created, 'Damage' creates a damage struct where 'd' is an array of strings.

Share this post


Link to post
Share on other sites
It should be noted that in this case, there are two nested aggregates -- the struct Damage, and its member array d. In general, each sub-aggregate in the aggregate initializer should be delimited by its own curly braces, for clarity's sake. The Standard, however, allows omitting everything but the outermost pair if there are no ambiguities. This is why the above code compiles. Some examples:

struct foo { int i; int a[2]; int j; };

foo f1 = { 1, { 2, 3 }, 4 }; // i==1, a[0]==2, a[1]==3, j==4
foo f2 = { 1, 2, 3, 4 }; // same as f1
foo f3 = { 1, 2 }; // i==1, a[0]==2, a[1]==0, j==0 (zero-initialization guaranteed!)
foo f4 = { 1, { 2 } }; // same as f3
foo f5 = { 1, 2, 3 }; // i==1, a[0]==2, a[1]==3, j==0
foo f6 = { 1, { 2 }, 4 }; // i==1, a[0]==2, a[1]==0, j==4
foo f7 = { 1, { }, 4 }; // i==1, a[0]==0, a[1]==0, j==4
foo f8 = { }; // i==0, a[0]==0, a[1]==0, j==0
foo f9; // contents random -- NOT zero-initialized! However, any and all
// member *objects* (as opposed to members of built-in types)
// WOULD be initialized by calling the default constructor.







It is interesting to note that the following is a valid syntax for initializing a variable of a built-in type:

int i = { 42 };

However, surprisingly (in light of the above) the following *isn't* well-formed:

struct s { int i; }
s s1 = { { 42 } };

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!