C++ Generate standard constructor - c++

I often find myself writing very simple classes instead of C-style structs. They typically look like this:
class A
{
public:
type mA;
type mB;
...
A(type mA,type mB,...) : mA(mA),mB(mB),... {}
}
Is that a sensible way of doing things? If yes, I was wondering whether there was any third party plugin out there or any handy short cut to automatically construct the text for the constructor (e.g. take the highlighted or existent member definitions, replace semicolons with commas, move everything on the same line, ...)? Thanks

Yes, just use plain aggregates:
struct A
{
type mA;
type mB;
...
};
Usage:
A x = { mA, mB, ... };
An aggregate has no custom constructors, destructor and assignment operator, and it allows for plenty of optimisations. Aggregate initialization with the brace syntax for example usually constructs the members in place without even a copy. Also you get the best possible copy and move constructors and assignment operators defined for you by the compiler.

EDIT: previous version was c99, not c++. now it is c++
i think you can use {} initialization instead of writing constructor. or is it in c++0x? c99? i am not sure. but it looks like:
struct A myA = { 3, 5};

I'd say it was a sensible way of doing it although OO fanatics might comment on the lack of encapsulation you have.
I know Visual Studio has code snippets built in which do half the job you are looking for but it depends on your IDE

Related

Silent breaking of constructor calls after adding initializer_list constructor

Let's consider the following:
#include <iostream>
#include <initializer_list>
class Foo {
public:
Foo(int) {
std::cout << "with int\n";
}
};
int main() {
Foo a{10}; // new style initialization
Foo b(20); // old style initialization
}
Upon running it prints:
with int
with int
All good. Now due to new requirements I have added a constructor which takes an initializer list.
Foo(std::initializer_list<int>) {
std::cout << "with initializer list\n";
}
Now it prints:
with initializer list
with int
So my old code Foo a{10} got silently broken. a was supposed to be initialized with an int.
I understand that the language syntax is considering {10} as a list with one item. But how can I prevent such silent breaking of old code?
Is there any compiler option which will give us warning on such cases? Since this will be compiler specific I'm mostly interested with gcc. I have already tried -Wall -Wextra.
If there is no such option then do we always need to use old style construction, i.e. with () Foo b(20), for other constructors and use {} only when we really meant an initializer list?
It's impossible to generate any warning in these cases, because presented behaviour of choosing std::initializer_list constructor over direct matches is well defined and compliant with a standard.
This issue is described in detail in Scott Meyers Effective Modern C++ book
Item 7:
If, however, one or more constructors declare a parameter of type
std::initializer_list, calls using the braced initialization syntax
strongly prefer the overloads taking std::initializer_lists. Strongly.
If there’s any way for compilers to construe a call using a braced
initializer to be to a constructor taking a std::initializer_list,
compilers will employ that interpretation.
He also presents a few of edge cases of this issue, I strongly recommend reading it.
I couldn't find such an option, so apparently in such cases you should use parentheses for classes that have initializer_list constructor, and uniform initialization for all other classes as you wish.
Some useful insights can be found in this answer and comments to it: https://stackoverflow.com/a/18224556/2968646
There are no compiler warnings and there never will be. It just doesn't make sense to warn on code doing something common like
std::vector vec{1};
Remember that the compiler only warns about really unwanted stuff, like undefined behavior. It has no way of knowing that in the definition above, you meant to call the constructor taking a size argument. For all it knows you actually want to have a vector with one element! It can't read your mind :)
The answer to your second question is basically yes. You can always add a dummy parameter like struct {} dummy; to avoid using the constructor with initializer list, but really, the only same solution is just to use parentheses instead of braces (or don't break the interface suddenly).
If you want to change every portion of code that uses list initialization, you can delete the initializer list constructor, change them to braces, and then implement the constructor correctly. I would consider such change a breaking one, and deal with it appropriately. The other idea would have been to come up with the initializer list use case beforehand, and implement it right away.

Will using brace-init syntax change construction behavior when an initializer_list constructor is added later?

Suppose I have a class like this:
class Foo
{
public:
Foo(int something) {}
};
And I create it using this syntax:
Foo f{10};
Then later I add a new constructor:
class Foo
{
public:
Foo(int something) {}
Foo(std::initializer_list<int>) {}
};
What happens to the construction of f? My understanding is that it will no longer call the first constructor but instead now call the init list constructor. If so, this seems bad. Why are so many people recommending using the {} syntax over () for object construction when adding an initializer_list constructor later may break things silently?
I can imagine a case where I'm constructing an rvalue using {} syntax (to avoid most vexing parse) but then later someone adds an std::initializer_list constructor to that object. Now the code breaks and I can no longer construct it using an rvalue because I'd have to switch back to () syntax and that would cause most vexing parse. How would one handle this situation?
What happens to the construction of f? My understanding is that it will no longer call the first constructor but instead now call the init list constructor. If so, this seems bad. Why are so many people recommending using the {} syntax over () for object construction when adding an initializer_list constructor later may break things silently?
On one hand, it's unusual to have the initializer-list constructor and the other one both be viable. On the other hand, "universal initialization" got a bit too much hype around the C++11 standard release, and it shouldn't be used without question.
Braces work best for like aggregates and containers, so I prefer to use them when surrounding some things which will be owned/contained. On the other hand, parentheses are good for arguments which merely describe how something new will be generated.
I can imagine a case where I'm constructing an rvalue using {} syntax (to avoid most vexing parse) but then later someone adds an std::initializer_list constructor to that object. Now the code breaks and I can no longer construct it using an rvalue because I'd have to switch back to () syntax and that would cause most vexing parse. How would one handle this situation?
The MVP only happens with ambiguity between a declarator and an expression, and that only happens as long as all the constructors you're trying to call are default constructors. An empty list {} always calls the default constructor, not an initializer-list constructor with an empty list. (This means that it can be used at no risk. "Universal" value-initialization is a real thing.)
If there's any subexpression inside the braces/parens, the MVP problem is already solved.
Retrofitting classes with initializer lists in updated code is something that sounds like it will be a common thing to happen. So people start using {} syntax for existing constructors before the class is updated, and we want to automatically catch any old uses, especially those used in templates where they may be overlooked.
If I had a class like vector that took a size, then arguably using {} syntax is "wrong", but for the transition we want to catch that anyway. Constructing C c1 {val} means take some (one, in this case) values for the collection, and C c2 (arg) means use val as a descriptive piece of metadata for the class.
In order to support both uses, when the type of element happens to be compatible with the descriptive argument, code that used C c2 {arg} will change meaning. There seems to be no way around it in that case if we want to support both forms with different meanings.
So what would I do? If the compiler provides some way to issue a warning, I'd make the initializer list with one argument give a warning. That sounds tricky not to mention compiler specific, so I'd make a general template for that, if it's not already in Boost, and promote its use.
Other than containers, what other situations would have initializer list and single argument constructors with different meanings where the single argument isn't something of a very distinct type from what you'd be using with the list? For non-containers, it might suffice to notice that they won't be confused because the types are different or the list will always have multiple elements. But it's good to think about that and take additional steps if they could be confused in this manner.
For a non-container being enhanced with initializer_list features, it might be sufficient to specifically avoid designing a one-argument constructor that can be mistaken. So, the one-arg constructor would be removed in the updated class, or the initializer list would require other (possibly tag) arguments first. That is, don't do that, under penalty of pie-in-face at the code review.
Even for container-like classes, a class that's not a standard library class could impose that the one-arg constructor form is no longer available. E.g. C c3 (size); would have to be written as C c3 (size, C()); or designed to take an enumeration argument also, which is handy to specify initialized to one value vs. reserved size, so you can argue it's a feature and point out code that begins with a separate call to reserve. So again, don't do that if I can reasonably avoid it.

C++ constructor initialization list alternative in C?

In C++, classes constructors can use initialization lists, which I am told is a performance feature that improves by avoiding extra assignments. So I wonder if there is a similar approach to achieve the same benefits in C for functions that basically serve the same purpose to initialize structs as C++ class constructors?
I am a little unclear on how exactly the feature works in a C++ compiler, so any additional info on the subject will also be appreciated.
C doesn't have any similar feature, however since C also doesn't have constructors, there is no danger of unnecessary assignments.
The bigger principle is that introducing one feature into a language often creates a need for additional features to reinforce the original. An trivial example is threads. If threads are built into the language as a feature, then there is the immediate question of how to synchronize them. Hence synchronization is also needed. So you see languages (like C) with no built-in threads or synchronization and languages with both, but not one without the other. Here, constructors is to threads as synchonization is to list initializers.
In C++ constructors, initialization lists allow the C++ compiler to constructor members in-place, at the location of the member variable, instead of using an assignment operator, copy-constructor, or move-constructor to initialize the member variable. See Section 10.6 of the C++ FAQ for more details.
In C, there are no such automatic operations provided by the C compiler. This means that the programmer controls all initialization directly, and no special-language features are required to avoid these extra operations.
To be a little more clear, consider what happens when you use assignment to initialize in a C++ constructor:
The member variable is first constructed with a default constructor
A temporary object is constructed
An assignment or move-assignment operator is called to re-initialize the member variable with the temporary.
Call the destructor on the temporary.
While some compilers can optimize this away in some situations, your mileage may vary, and no C++ compiler can optimize these steps away in all situations. Now, consider how a programmer would exactly duplicate these steps in C:
void my_struct_init(struct my_struct* sp)
{
member_init_default(&sp->the_member); /* default constructor for member */
struct member memb; /* temporary on stack */
member_init_other(&memb, ...params...); /* initialize memb */
member_assign(&sp->the_member,&memb); /* assign member */
member_finalize(&memb); /* finalize the temporary */
}
Few C programmers would do this (without good reason). Instead, they would automatically code the optimization:
member_init_other(&sp->the_member, ...params...);
The feature exists in C++ because the compiler does a lot of automatic things for the programmer. This is often makes life easier for the programmer, but requires features like initialization lists to help the compiler generate optimum code. C compilers present a much simpler model of the underlying machine, do fewer things automatically, and thus require fewer features (though not necessarily less work) to generate similarly optimal code.
There is no such feature in C. The closest thing is designated initializers.
You can write a separate function and call it when you are creating an object from a class and then pass it to it:
C:
typedef struct {
int x;
}mine;
void mine_initializer(mine* me)
{
me->x = 4; //initialization
}
int main(void)
{
mine me;
mine_initializer(&me);
return 0;
}
Also you can do that in C++:
struct mine{
int x;
void initialize()
{
x = 4; //initialization
}
};
void main(void)
{
mine me;
me.initialize();
printf("%d",me.x);
}
this will output 4 as the result.

How to workaround Visual C++ standards non compliance?

According to this question, Visual C++ 2005 (and also 2008/2010) does not zero initialize correctly data members.
Since I have a code which requires the standard behaviour, and which crashes in release mode (and not in debug), I suspect the issue comes from here.
Now, the problem is that the code base is quite large, and manually inspecting classes is difficult.
Is there a compiler option to trigger a warning on this non standard behaviour of MSVC ? With /W4, you get the warnings about some non standard extensions (conversions from rvalues to references, missing typename keyword), but not for this particular problem.
EDIT: I suspect code like that to cause trouble (pasted from the linked question)
include <cassert>
struct B { ~B(); Foo* m; };
int main()
{
B * b= new B();
assert ( b->m ==0);
}
in other portions of the code I have things like
B* b = new B();
and then, later,
if (b->m) { b->m->bar(); }
and b->m should be zero per the standard, but it's likely not (except in debug mode). I would like to detect such code (like a warning "m used without being initialized" or something)
Is this about foo::foo () : member () { }? Paste some example (code) of the problem you are seeing. In standard C++ implementation, the member should have value 0 (assuming it is of a fundamental type). However some older compilers do not do/implement this correctly and just leave it uninitialized. AFAIK there is no warning for this. You will have to go through the code and initialize the member with 0 or other value explicitly.
asper charles comment below, the compiler should be zero init before the ctor is called.
8.5 An object whose initializer is an empty set of parentheses, i.e., (), shall be
value-initialized. ... Value-initialization for such a class object may be implemented
by zero-initializing the object and then calling the default constructor
12.1/7 A non-user-provided default constructor for a class ... performs the set of
initializations of the class that would be performed by a user-written default
constructor for that class with no ctor-initializer (12.6.2) and an empty
compound-statement.
12.6/4 If a given non-static data member or base class is not named by ... in
initialiser list ... the entity is not initialized.
however, remember effective C++, if you declare a dtor then you should also declare a copy ctor, ctor and self-assignment (even if you declare as private)
Don't work around it, attack it directly.
You'll need a C++ parser. Using the parser you'll have to track the types of variables which have no been properly assigned within each constructor of the classes. Once you've got that going it's simply a matter of inserting the proper syntax to make initialization happen in a desirable way. It's not a simple script to write but it'll save you loads of headache later.
FIrst step is just getting output from the parse tree to label problems for you:
class Foo{
public:
Foo(int a) : mA(a){}
private:
int mA, mB;
};
you'll want your script producing messages like: In class Foo :: missing initializer mB
Then get brave and transform that output into an instruction set to traverse the parse tree and insert missing items so that your code looks like:
class Foo{
public:
Foo(int a) : mA(a), mB(0){}
private:
int mA, mB;
};
So my best advice is to not try to work around the issue, attack it directly. If you still have problems after that, grab your nearest static code analyzer and memory analyzer. Those are the tools that will help you best of all.
Are you sure you (the people purportedly citing the ISO C++ Standard) are actually citing it? And not being confused with the text for updated versions specified in TR's which are not actually Standards? Or C++11 which probably will be soon, but one can hardly expect MS to conform to something not yet officially a Standard.

Initializing member variables

I've started to pick up this pattern:
template<typename T>
struct DefaultInitialize
{
DefaultInitialize():m_value(T()){}
// ... conversions, assignments, etc ....
};
So that when I have classes with primitive members, I can set them to be initialized to 0 on construction:
struct Class
{
...
DefaultInitialize<double> m_double;
...
};
The reason I do this is to avoid having to remember to initialize the member in each constructor (if there are multiple constructors). I'm trying to figure out if:
This is a valid pattern?
I am using the right terminology?
This is a valid pattern?
It's a known "valid" pattern, i would say. Boost has a class template called value_initialized that does exactly that, too.
I am using the right terminology?
Well, your template can be optimized to have fewer requirements on the type parameter. As of now, your type T requires a copy constructor, unfortunately. Let's change the initializer to the following
DefaultInitialize():m_value(){}
Then, technically this kind of initialization is called value initialization, starting with C++03. It's a little bit weird, since no kind of value is provided in the first place. Well, this kind of initialization looks like default initialization, but is intended to fill things with zero, but respecting any user defined constructor and executing that instead.
To summarize, what you did was to value initialize an object having type T, then to copy that object to m_value. What my version of above does it to value initialize the member directly.
Seems like a lot of work to avoid having to type m_double(0). I think it's harder to understand at first glance, but it does seem fine as long as everything is implemented properly.
But is it worth it? Do you really want to have to #include "DefaultInitialize.h" everywhere?
To clarify, basically, you're:
Making your compile times longer because of the includes.
Your code base larger because you have to manage the deceptively simple DefaultInitialize class
Increase the time it takes other people to read your code. If you have a member of a class that's a double, that's natural to me, but when I see DefaultInitialize, I have to learn what that is and why it was created
All that because you don't like to type out a constructor. I understand that it seems very nice to not have to do this, but most worth-while classes I've ever written tend to need to have a constructor written anyway.
This is certainly only my opinion, but I think most other people will agree with it. That is: it would be handy to not have to explicitly initialize members to 0, but the alternative (your class) isn't worth it.
Not to mention that in C++0x, you can do this;
class Foo
{
private:
int i = 0; // will be initialized to 0
}
Some compilers don't properly implement value initialization. For example, see Microsoft Connect, Value-initialization in new-expression, reported by Pavel Kuznetsov.
Fernando Cacciola's boost::value_initialized (mentioned already here by litb) offers a workaround to such compiler bugs.
If you're just initializing basic types to zero, you can override new and have it memset allocated memory to zero. May be simpler. There are pros and cons to doing this.