3

My question: When a structure has c-tor, why can't I statically initialize it ?

My compiler claims :

type `myStruct' must be initialized by constructor, not by `{...}'

Why is that ? I'm using gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

To illustrate, here is the struct that is rejected by the compiler.

struct myStruct
{
    int a;
    double b;

    myStruct() { a= 0; b = 0.0; }
}

void main()
{
    myStruct ms = {7, 7.7}; // Now this compiler does not accept.
} 
Steve Guidi
  • 19,700
  • 9
  • 74
  • 90
Sold Out
  • 1,321
  • 14
  • 34
  • Sample code that costs you hours literally to format, until it gets accepted !! It claims I do not have properly indented code by 4 spaces. I do. I can count to 4. struct myStruct { int a; double b; // Now I add here a default c-tor myStruct() { a= 0; b = 0.0; } } void main() { myStruct ms = {7, 7.7}; // Now this compiler does not accept. } – Sold Out Aug 28 '12 at 15:46
  • @Peter No need to do that by hand. Paste the code into the editor, select it, hit the button (for Ctrl-K). –  Aug 28 '12 at 15:48
  • I suppose you are talking about array initialization syntax? Because you can only initialize POD types this way... – Fiktik Aug 28 '12 at 15:48
  • 2
    What code do you think you need to see, @Robert? The question seems perfectly clear to me without any code. – Rob Kennedy Aug 28 '12 at 15:49
  • @RobKennedy Peter asked why he was getting a specific error, but I'm assuming he also wants a solution that will give the effect he desires. For the former, code does not help. For the latter, code is necessary. – robert Aug 28 '12 at 15:51
  • @delnam Even better, if you're using Firefox: the It's all text! add-in, which allows you to edit POST boxes using any editor you choose. (I edit most of my postings here using `vim`.) – James Kanze Aug 28 '12 at 16:17
  • @Fiktik That's wrong. You can initialize any aggregate this way; it certainly doesn't have to be a POD. – James Kanze Aug 28 '12 at 16:19

4 Answers4

7

The inclusion of a user-defined c-tor means it's no longer an aggregate type. This would also be the case if there was no user-defined c-tor for the struct itself, but you have a non-static data-member of the struct that is not a POD or aggregate type.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • Many thnax for super-fast answers. The code got serialize - though my question got grasped :) :) Thanx for help again ! – Sold Out Aug 28 '12 at 15:51
  • @Jason you mean aggregate, not POD. Not all aggregates are POD (and vice versa in C++11). – ecatmur Aug 28 '12 at 16:18
  • Super-fast, but irrelevant. Who said anything about PODs. He's asking about aggregate initialization, which doesn't require a POD, but (surprise, surprise) and aggregate. – James Kanze Aug 28 '12 at 16:20
  • @JamesKanze Okay, fixed ... you're having fun with me today! :-) – Jason Aug 28 '12 at 16:22
  • How does C++11 change this? I know it does things to initializers to help with non-PODs, but does it effect aggregates, just PODs, ...? – ssube Aug 28 '12 at 16:24
  • @peachykeen uniform initializer syntax will call a constructor if one is available with the appropriate number of parameters. It will not bypass constructors directly to initialize members. – ecatmur Aug 28 '12 at 16:27
  • As @ecatmur points out, in both C++11 and C++03, only aggregates can be initalized using an initializer list. In C++11 you also can initialize a non-aggregate with an initializer list if there is a constructor that takes one of the appropriate type. The confusion with PODs is that in C++03 all PODs are aggregates, but in C++11 not all PODs are aggregates. In C++11 you can have a non-copy, non-default constructor and still be a PODs, but not an aggregate. – Jason Aug 28 '12 at 16:27
  • @Jason Having fun with everyone:-). But in this case, the difference is important. It's very frequent (for me, at least) to have `struct` with `std::string` members, and to use aggregate initialization. – James Kanze Aug 28 '12 at 16:43
  • @Jason "In C++11 you can have a non-copy, non-default constructor and still be a PODs, but not an aggregate." I don't think so. In §9/10: "POD struct109 is a non-union class that is both a trivial class and a standard-layout class". A trivial class must have a trivial default constructor, and a class with any user defined constructor can never have a trivial default constructor. To be trivial, the default constructor must be generated by the compiler, and the compiler will not generate one if there is any user defined constructor. – James Kanze Aug 28 '12 at 16:49
  • @JamesKanze What about Section 12.1/5? It seems like it's saying you can have a user-defined constructor and still have a trivial default constructor ... Did I miss something? – Jason Aug 28 '12 at 17:12
  • @Jason A user defined constructor is never trivial. And the second sentence in §12.1/5 is "If there is **no** user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted." (Emphesis added.) If there is any user defined constructor, the only way you can have a default constructor is to define one yourself, which automatically makes it non-trivial. (But perhaps declaring `MyClass() default;` results in a trivial default constructor, even with other user defined constructors. I've not thought about this.) – James Kanze Aug 28 '12 at 17:33
  • @JamesKanze Okay, the `MyClass() = default;` example was what I was thinking of as the reason you can have user-defined non-copy, non-default constructors and still be a PODs, but not an aggregate, in C++11 – Jason Aug 28 '12 at 17:45
4

Because the language specifies it that way...

The reason is that the constructor is the designated way to initialize the object to a valid state, so just dumping values into fields directly makes no sense.The ideas is that you either have a collection of values, or a self contained object but what you want to do would make it a little of both.

jcoder
  • 29,554
  • 19
  • 87
  • 130
3

Only aggregates may be initialized with an initializer list. Per 8.5.1:1, the inclusion of a user-provided constructor prevents a struct or class from being an aggregate:

8.5.1 Aggregates [dcl.init.aggr]

1 - An aggregate is an array or a class (Clause 9) with no user-provided constructors [...]

In C++03,

8.5.1 - Aggregates [dcl.init.aggr]

1 - An aggregate is an array or a class (clause class) with no user-declared constructors [...]

Aggregates are distinct from PODs ( 9:10); not all aggregates are POD and not all PODs are aggregates; a class with a user-provided destructor could be an aggregate but not a POD, while a class with a non-copy non-default constructor could be POD but not an aggregate.

Demonstration:

#include <type_traits>
#include <iostream>

struct non_pod_aggregate { int i, j; ~non_pod_aggregate() {} };
struct non_aggregate_pod { int i, j; non_aggregate_pod(int) {}
    non_aggregate_pod() = default; };

int main() {
    std::cout << std::is_pod<non_pod_aggregate>::value << '\n'; // false
    std::cout << std::is_pod<non_aggregate_pod>::value << '\n'; // true
    non_pod_aggregate{0, 0};
    // non_aggregate_pod{0, 0}; // does not compile
}

In C++03, all PODs ( 9:4) are aggregates, but it is still possible to have aggregates that are not PODs; as above, a user-provided destructor is enough to disqualify a struct from being POD.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Keep in mind he's using a pretty old version of gcc, so it's going to be C++03 and not C++11 ... C++11 has relaxed the rules a bit on what is considered a POD-type and what is not when it comes to constructors. – Jason Aug 28 '12 at 16:00
  • 1
    Section 9/4 of the C++03 standard states: "*A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator and no user-defined destructor.*" ... So in order to be an aggregate type, the POD-struct can't have a user-declared constructor of any type, and that includes a non-copy non-default constructor. – Jason Aug 28 '12 at 16:09
  • @Jason this is aggregate initialization, so the POD rules are not completely relevant. – juanchopanza Aug 28 '12 at 16:17
1

In C++03 list-initialization only works for aggregates. You need to change your code to call the constructor:

myStruct ms;

If you want to be able to specify values for all of the members, you need to add a constructor taking enough arguments:

struct myStruct
{
    int a;
    double b;

    myStruct() : a(), b() { }
    myStruct(int a, double b) : a(a), b(b) { }
};

void main()
{
    myStruct ms(7, 7.7);
} 
Mankarse
  • 39,818
  • 11
  • 97
  • 141