19

I have a class and a const variable.

struct A 
{
    int b;
};

A const a;

The class A is POD and can be initialized like this.

A const a = { 3 };

IMHO, it looks fine to have a constructor like this.

struct A 
{
    int b;

    A(int newB) : b(newB)
    {
    }
};

But Clang assumes A as non-aggregate type. Why I can't have constructor like that? Or should I do something else?


I modified question to present my original meaning. I had wrote the struct as class by mistake, and sorry for @Johannes about confusing :)

Jonas
  • 121,568
  • 97
  • 310
  • 388
eonil
  • 83,476
  • 81
  • 317
  • 516
  • Eonil: I believe, my answer clarifies your all doubts, especially the quotation from the Standard. – Nawaz Mar 26 '11 at 14:27
  • You need to decide what you question is about: 1) POD-types or 2) simply the ability to use the `{}` initializer (i.e. aggregates). At this time it is not clear what specifically is the problem. – AnT stands with Russia Mar 26 '11 at 14:41
  • @Nawaz Thanks for care. Your answer is what I want! – eonil Mar 26 '11 at 14:44
  • @AndreyT My question was about constructor on POD type. I had wanted to use constructor syntax instead of `{...}` syntax. But now I know my idea was wrong. – eonil Mar 26 '11 at 14:46
  • @AndreT: Is it not both same? As in my opinion, in C++03, only aggregate (that means, all variants of it) can be initialized with `{}`? And aggregate-class is nothing but POD-class, right? – Nawaz Mar 26 '11 at 14:46
  • @Nawaz: No, that's not even remotely correct. For a simple example, an array of `std::string` objects is an aggregate, but not a POD. And you can initialize such array with `{}` initializer even though it is not a POD. – AnT stands with Russia Mar 26 '11 at 14:55
  • @Eonil: The ability to use the `{}` initializer syntax depends on whether the object is an *aggregate* or not. Being an *aggregate* has very little to do with being a *POD* type. If what you care about is the `{}` initializer, then you can forget about POD - it has nothing to do with it whatsoever. – AnT stands with Russia Mar 26 '11 at 14:56
  • @AndreyT I was just confused about whether POD type can have user-defined ctor or not. Because documents about POD does not mention about ctor, and the mention was in aggregation type section :) And I have to care about POD because its the only type can be passed to C functions like GL... – eonil Mar 26 '11 at 15:12
  • @AndreyT: I think, it's implicitly clear from OP's sample code that he wants POD-struct/class, not an array! – Nawaz Mar 26 '11 at 15:16
  • @Nawaz: There's absolutely no difference whether it is an array or not. All aggregates are the same in this respect. Another example would be a struct with `std::string` members and no other members. Is it a POD? No. Is is an aggregate? Yes. So, how is your "the same" doing in this case? – AnT stands with Russia Mar 26 '11 at 16:13

3 Answers3

20

POD means Plain Old Data type which by definition cannot have user-defined constructor.

POD is actually an aggregate type (see the next quotation). So what is aggregate? The C++ Standard says in section §8.5.1/1,

An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected nonstatic data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).

And section §9/4 from the C++ Standard says,

[....] 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. Similarly, a POD-union is an aggregate union 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. A POD class is a class that is either a POD-struct or a POD-union.

From this, its also clear that POD class/struct/union though cannot have user-defined assignment operator and user-defined destructor also.


There are however other types of POD. The section §3.9/10 says,

Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to member types (3.9.2), and cv-qualified versions of these types (3.9.3) are collectively called scalar types. Scalar types, POD-struct types, POD-union types (clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called POD types.

Read this FAQ : What is a "POD type"?

Nawaz
  • 353,942
  • 115
  • 666
  • 851
6

The class A is POD and can be initialized like this

Sorry, that is wrong. Because b is private, the class is not a POD.

But Clang assumes A as non-aggregate type. Why I can't have constructor like that? Or should I do something else?

This is a limitation of C++ as it exists currently. C++0x will not have this limitation anymore. While in C++0x your type is not a POD either, your initialization will work (assuming that you make that constructor public).

(Also, I think a better term for you to use here is "aggregate". The requirement for using { ... } is that your class is an aggregate. It doesn't have to be a POD).

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 1
    Oh thanks. It was my mistake using `class` instead of `struct`. I'm sorry. I couldn't care about default access. I updated my question. And comment for aggregate but non-POD types is helpful itself :) – eonil Mar 26 '11 at 14:22
2

The other answers describe the POD rules pretty well. If you want to get a similar initialization style to a constructor for a POD you can use a make_-style function, for example:

struct A
{
    int i_;
};

A make_A(int i = 0) 
{
    A a = { i }; 
    return a; 
}

now you can get initialized POD instances like:

A a = make_A();
shuttle87
  • 15,466
  • 11
  • 77
  • 106
Inverse
  • 4,408
  • 2
  • 26
  • 35