4

I'm reading through Programming Principles and Practice C++, and came across the following piece of code which I don't think was well explained

struct Day {
    vector<double> hour{vector<double>(24,-777) };
};

What is happening here? I usually use this initializer when I need a vector of a certain length with default values:

vector<double> hour(24, -777);

However, this way of initializing does not work inside the struct,

struct Day {
    vector<double> hour(24, -777);
};

Results in a compile error

Error (active)      expected a type specifier   HelloWorld  d:\Visual Studio 2015\HelloWorld\HelloWorld\HelloWorld.cpp  11  
Error (active)      expected a type specifier   HelloWorld  d:\Visual Studio 2015\HelloWorld\HelloWorld\HelloWorld.cpp  11  
Error   C2059   syntax error: 'constant'    HelloWorld  d:\visual studio 2015\helloworld\helloworld\helloworld.cpp  11  

Looking for an explanation behind the initializers.

I'm using MS Visual Studio 2015

Adrian Muljadi
  • 168
  • 1
  • 15
  • What do you mean by _initializing does not work inside the struct_? Maybe it's unsupported syntax by VS? It compiles fine [here](https://ideone.com/fLXQ82). – Algirdas Preidžius Nov 30 '16 at 11:40
  • @AlgirdasPreidžius It also compiles fine in Visual Studio 2015, see my answer: http://stackoverflow.com/a/40888321/2642059 – Jonathan Mee Nov 30 '16 at 12:34
  • @JonathanMee That's why I asked for clarification, why did the OP mean by _does not work_, and I don't have MSVS 2015 at my disposal, so I couldn't test it myself. In addition to that, I have seen functionality differ for different update versions, of the same major version MSVS, so without specifying those, it's unclear if you are using the same version of MSVS (even though it's MSVS2015). – Algirdas Preidžius Nov 30 '16 at 12:40
  • Apologies for lack of details, can you please see the edits? – Adrian Muljadi Nov 30 '16 at 12:50
  • @AdrianMuljadi That doesn't work because C++ doesn't support that syntax for class member declaration. You can learn more about the requirements for default member initialization in part **2** of my answer. – Jonathan Mee Nov 30 '16 at 15:25
  • @AdrianMuljadi Just FYI, if you want to communicate via comment on http://www.stackoverflow.com you should use "@" followed by the username that way the person you're communicating with will be notified of a new message. – Jonathan Mee Nov 30 '16 at 15:46

4 Answers4

4
vector<double>(24,-777)

This creates a temporary std::vector with 24 values of -777.

Then the hour vector is constructed by using that temporary, using the move constructor.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
0

This works fine in Visual Studio 2015: http://rextester.com/WIS16088 Perhaps you're doing something else wrong in your code?

Anyway to explain what's going on here:

  1. The behavior of curry braces here was clarified in N3922 which in this case will distill to a braced-init-list, there is some great further reading here: What Is a Curly-Brace Enclosed List If Not an intializer_list?
  2. These curly braces are providing default member initialization for the member hours, as provided by C++11. This is the value that hours will take on unless it:

Also appears in the member initialization list in a constructor

  1. Finally let's talk about the value that is being used in the curly braces which is hours brace-init-list, that's clearly a vector<int> http://en.cppreference.com/w/cpp/container/vector/vector defines that as the 2nd constructor which:

Constructs the container with count copies of elements with value value

So what you'll end up with is hours initialized to contain 24 ints of value -777 if it is default initialized.

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
0

C++11 lifted restrictions on in-class initialization and introduced initializer_list constructors for collections allowing you to write this:

struct Day {
    std::vector<double> hours = { 1.0, 2.0, 3.0 };
};

However for your case (vector filled with 24 values of -777.0), you don't want initializer_list - you still can use old constructor, but unfortunately you can't combine it with auto (unless it's static constexpr literal member). You should probably use 24u to parameter, that's intended to be converted to size_t and double for parameter intended to be value (for readability):

struct Day {
    std::vector<double> hours = std::vector<double>(24u, -777.);
};

Example with using auto to initialize some member:

struct Day {
    static constexpr auto default_hours_size = 24u;
    std::vector<double> hours = std::vector<double>(default_hours_size, -777.);
};
Patryk Obara
  • 1,847
  • 14
  • 19
-1

Your solution should be valid. If it does not work, try doing this:

struct Day {
    vector<double> hour = vector<double>(24,7);
};
Adam Hunyadi
  • 1,890
  • 16
  • 32
  • The initialization syntax used in the question is already valid in Visual Studio 2015, see my answer: http://stackoverflow.com/a/40888321/2642059 So no changes need to be made, that said this does not attempt to address the actual question of: "What is happening here?" – Jonathan Mee Nov 30 '16 at 12:28