Table of Contents Situation.....................................................................................................................................................1 Solutions.....................................................................................................................................................3 Solution #1: Language change to always use additional {}..................................................................3 Solution #2: explicit argument to always use additional {}..................................................................3 Solution #3: std::explicit_list_initializer addition.................................................................................4 Solution #4: std::explicit_list_initializer addition with language support.............................................4 Solution #5: std::implicit_list_initializer addition with language support............................................5 Other Ideas.................................................................................................................................................5 Exact Types...........................................................................................................................................5 Recommendation.......................................................................................................................................6 References..................................................................................................................................................7

Situation Calling a constructor with braces {} syntax is fixing some old issues with C++ constructors: MyClass obj(); // oups, declaring a function MyClass obj2(MyOtherClass()); // oups, declaring a function

versus: MyClass obj{}; MyClass obj2{MyOtherClass()}; // ...or even... MyClass obj3{MyOtherClass{}};

For these reasons, some respected members of C++ community like Herb Sutter, hint to use braces syntax pretty much always. We can expect a lot of programmers to follow the advice. However, initializer_list constructor is greedy: struct MyClass { MyClass(std::initializer_list list); MyClass(bool value); ... MyClass obj{false}; // Calling MyClass(std::initializer_list list)

This could be considered worse than what the syntax is fixing. If you look back again at these cases: MyClass obj(); // oups, declaring a function MyClass obj2(MyOtherClass()); // oups, declaring a function

Such mistakes typically stay on the programmer's own machine. The programmer might spend time investigating something right in front of its eyes, but it should not be submitted in source control. However, if you have this:

struct MyClass { MyClass(bool value); ...

And elsewhere in the code base, or even in a client using the code, there's something like: MyClass obj{false};

And then, much later, someone adds that constructor: MyClass(std::initializer_list);

The result is a regression that can be silent at compile-time. Not only it's breaking code, but not even code submitted by the culprit. What's interesting, is that standard library classes are doing exactly that. But the standard library had an unfair advantage, since the changes were introduced by vendors at the exact same time as the language feature itself. For example, initializer_list constructor could not have been added to std::string if that code could have existed before: std::cout << std::string{4, ' '};

In the future, with their own code bases, programmers won't have the same luxury as the one enjoyed by the standard library, and will face risks introducing such an initializer_list constructor in existing classes. Thus, technical leaders are in a situation where more and more programmers are likely to use the braces initialization {} syntax, and they will probably try to come up with guidelines instead of fighting it. That being said, a guideline such as "only use that syntax if you are 100% sure the class will never ever get a initializer_list constructor or if you are using an initializer_list constructor" sounds a bit... non-agile. If the default language behavior cannot be changed, it would be great to at least have a way to put the guideline on how to add an initializer_list constructor instead. Herb Sutter suggested the guideline of not adding an intializer_list constructor when it can conflict with another constructor. Multiple initializer_list constructors in the standard library are violating this rule. And applying this guideline to a template container pretty much means to not have any constructor taking only common types like integers and booleans, which is unrealistic. So at the moment a guideline about initializer_list constructors must realistically mention how constructors are called as well. The reflex for some programmers facing some previous examples might be to add explicit to the initializer_list constructor, which is doing something else, preventing copy-initialization: struct MyClass { explicit MyClass(std::initializer_list); }; MyClass obj{1}; compiles MyClass obj2 = {1}; // doesn't compile

And it does make sense. What is wanted is not to prevent MyClass to be implicitly created, but instead make the construction from an initializer_list more explicit. All listed solutions in this document will

therefore use explicit/implicit nomenclature. All listed solutions also assume that what is wanted is some way to achieve such behavior, regardless if you have to opt-in for it or if it is the default: MyClass MyClass MyClass MyClass

obj1{value}; // non-initializer_list constructor obj2{{value}}; // initializer_list constructor obj3{value1, value2}; // non-initializer_list constructor obj3{{value1, value2}}; // initializer_list constructor

Solutions Solution #1: Language change to always use additional {} A common proposed solution is to change the language to always have to use additional {} to call initializer_list constructors: struct MyClass { MyClass(bool value); MyClass(std::initializer_list); }; MyClass obj1{false}; // calling MyClass(bool) MyClass obj2{{false}}; // calling MyClass(std::initializer_list)

Such a change in the language could be made in 2 passes, with a first pass as compile-time errors any situation changing behavior. Pros: • • Cons: • •

Would eliminate issue of bugs easily introduced by adding initializer_list constructor. Compilers could warn about breaking change situations. Breaking change. No workaround for some situations where current rules are useful.

Solution #2: explicit argument to always use additional {} A possible solution would be add a new placement for explicit keyword to introduce the new rule: struct MyClass { MyClass(bool value); MyClass(explicit std::initializer_list); }; MyClass obj1{false}; // calling MyClass(bool) MyClass obj2{{false}}; // calling MyClass(std::initializer_list)

Pros:

• •

Provides a safer way to add an initializer_list constructor. Guideline is on how to add an initializer_list constructor, not on when to use {} syntax to call constructors.

Cons: • Programmers must opt in for the safer way. • Adds a new placement for explicit, resulting in possible confusion. • Might make more sense if explicit is supported on more argument types than just std::initializer_list.

Solution #3: std::explicit_list_initializer addition template struct explicit_initializer_list { initializer_list data; constexpr explicit_initializer_list(initializer_list data_) :data(data_) {} };

This is however not working well when competing with other constructors: struct MyClass { MyClass(bool value); MyClass(std::explicit_initializer_list); }; MyClass obj{false}; // calling MyClass(bool) MyClass obj{{false}}; // calling MyClass(bool), doesn't work

Pros: • Simply adding a type. No language change. Cons: • Programmers must opt in for the safer way. • Doesn't work as typical programmer would expect in multiple scenarios.

Solution #4: std::explicit_list_initializer addition with language support struct MyClass { MyClass(bool value); MyClass(std::explicit_initializer_list); }; MyClass obj{false}; // calling MyClass(bool) MyClass obj{{false}}; // calling MyClass(std::explicit_initializer_list)

Pros: • Provides a safer way to add an initializer_list constructor.



Guideline is on how to add an initializer_list constructor, not on when to use {} syntax to call constructors. No breaking change.

• Cons: • Programmers must opt in for the safer way. • Language rules for 2 different initializer lists.

Solution #5: std::implicit_list_initializer addition with language support This is a twist of solution #1 and #4, by adding a new type, std::implicit_initializer_list, to have current behavior of std::initializer_list, while the new behavior for std::initializer_list is more explicit. It is introducing a breaking change, but the workaround is very easy, especially for standard library which can switch to implicit_initalizer_list constructors. Pros: • • • •

No need to opt in to the safer behavior. While making a breaking change, the workaround is very easy. Provides better long term value for the language. Standard library initializer_list constructors could be converted to implicit_initializer_list, reducing breaking change effect. Compilers could warn about breaking change situations.

• Cons: • Breaking change. • Language rules for 2 different initializer lists. • Breaking change could result in different constructors being called, resulting in run-time errors, not only compile-time.

Other Ideas Exact Types The problem could be considered to be much more with examples where the behavior would not be expected by the average C++ programmer: struct MyClass { MyClass(std::initializer_list list); MyClass(bool value); ... MyClass obj{false}; // could surprise many programmers

Than something like: struct MyClass { MyClass(std::initializer_list list); MyClass(int value);

... MyClass obj{1};

// less surprising

Therefore it could be considered to have explicit initializer_lists (whatever their syntax) to be forced to be initialized with exact types: struct MyClass { MyClass(bool value); MyClass(explicit std::initializer_list); }; MyClass obj1{false}; // calling MyClass(bool) MyClass obj2{{false}}; // calling MyClass(bool) MyClass obj3{4.5f}; // calling MyClass(std::initializer_list)

It doesn't look convincing and would not behave the same way as raw arrays. But more importantly, it doesn't seem to be what is better translating an explicit intention. The approach doesn't look right with templates as well. Suppose you have the following template container and would like to provide an initializer_list constructor: template struct MyList { MyList(int capacity); …

Exact types matching doesn't help. If the constructor is already called with braces {}, it will no more call the same constructor. There's one case that even with an explicit initializer_list will be broken, but it's honestly marginal: MyList list{{4}};

Recommendation Solution #2 and #4 look like decent solutions that are opt-in, and just ruling out the explicit initializer_list constructor is the specific context of single braces {}. They would not break existing code. Solution #2 main problem is really to hint that explicit could be supported on more argument types, another debate completely. With solution #4, there's a decision to take if the following is supported: struct MyClass { MyClass(std::initializer_list); MyClass(std::explicit_initializer_list); }; MyClass obj{false};

// compiles?

// calling MyClass(std::initializer_list)

MyClass obj{{false}};

// calling MyClass(std::explicit_initializer_list)

It could be simply that this is not supported to have both explicit and non-explicit initializer_list constructors, a rule that could be more intuitive with solution #2.

References GotW #1 Solution: Variable Initialization – or Is It? http://herbsutter.com/2013/05/09/gotw-1-solution/

Table of Contents Situation -

The result is a regression that can be silent at compile-time. Not only it's breaking ... been added to std::string if that code could have existed before: std::cout ...

119KB Sizes 0 Downloads 48 Views

Recommend Documents

Table of Contents - Groups
It is intended for information purposes only, and may ... It is not a commitment to ... Levels of Security, Performance, and Availability. MySQL Enterprise. Audit ...

Table of Contents - GitHub
random to receive a new welfare program called PROGRESA. The program gave money to poor families if their children went to school regularly and the family used preventive health care. More money was given if the children were in secondary school than

Table of Contents
Feb 24, 2012 - Commission for Africa (ECA) [South African. Mission]. E-mail: [email protected] Mail: PO Box 1091, Addis Ababa, ETHIOPIA.

Table of Contents
The Archaeological Evidence for the Jafnids and the Nas ̣rids. 172. Denis Genequand. 5. Arabs in the Conflict between Rome and Persia, AD 491–630. 214.

Table of contents - GitHub
promotion about guide login_id login ID login_password login password email_generate_key generated key for certificating email email_certified_at timestamp ...

Table of Contents
24 February 2012. Source: Directory of Contacts www.gcis.gov.za/gcis/pdf/contacts.pdf ...... E-mail: [email protected] Mail: PO Box 11447, Asmara, ...

table of contents -
This component is installed locally in the PC or notebook of the CAMS2 subscriber. ... 9. You can choose the default extraction path or select a different path.

Table of Contents
Robots offer advantages not found in on-screen agents or technology embedded in ..... archive Proceedings of the 3rd ACM/IEEE international conference on.

Table of Contents
U.S. Public Finance. Moody's Global. Special Comment. Table of Contents: Summary Opinion. 1. Short Term Fund Depositors Have More. Liquidity Available Than Originally ..... Moody's Corporation (MCO) and its wholly-owned credit rating agency subsidiar

Table of Contents -
Insert Information Protection Policy Classification from Slide 12. 23. Replication Monitoring. ▫ Auto-discovers replication topology. ▫ Master/Slave performance monitoring. ▫ Replication advisor. ▫ Best practice replication advice. "I use the

table of contents
numerous notes providing additional information on the use of each material. 2. A tabulation of ...... API RP-520. 2.4.1. Determining Reaction Forces In An Open-Discharge System. The following formula is based on a condition of critical steady-state

Table of Contents -
Does Orika automatically map fields with the same property name? ..... In this example our converter was anonymous, and Orika use the converter's canConvert .... For example, suppose you have the following domain (getters/setters omitted):.

Table of Contents -
When do I need to explicitly register mapping for 2 types? ..... For example, suppose you have the following domain (getters/setters omitted): class Envelope.

Table of Contents
Streams ....................................................................................................................................................612. Erchi Xu, Bo Liu, Liyang Xu, Ziling Wei, Baokang Zhao, and Jinshu Su. Efficient Malicious

table of contents
pleasant daily practice of responsible, purposeful decisions for developing ..... has sat out a minimum of one full semester. He may not return ..... Lunches, homework, books and other items may be left in the school ..... Updated: August 2018. 49.

Table of Contents
3) To avoid Network congestion, Bidder is recommended to upload file size of up to. Maximum 35 MB per ...... group shall be fully responsible to carryout the work as per standards and all code requirements. ...... xix) Structures should not be worked

Table of Contents
Oct 26, 2007 - In a study of 52 Japanese patients with chronic urticaria without other ..... chronic urticaria patients, more than 50% responded to an elimination diet (48). • Another large series showed improvement in only about one third of patie

Table of Contents
GPS. Global Positioning System. GSM. Global Standard for Mobile ..... Two major tracking techniques are used for positioning: Kalman Filter (KF) and ...... [Wan00] E.A. Wan, R. Van Der Merwe, “The unscented Kalman filter for nonlinear.

Table of Contents
the actors in the problematic system to make theory a reality. .... example, associating Osama bin Laden's terrorist organization with Islam has proven to ...... 1992, Ramzi Yousef traveled from Peshawar to New York under a false name and Ali.

table of contents
APPENDIX E. Diagram of Room Worksheet for Radon Measurements .... or batteries to operate, such as charcoal detectors or alpha track detectors. "Perimeter ..... A description of all measurement devices the applicant or licensee plans to use ...

Missionary Messages - Table of Contents - Swartzentrover.com
gone abroad from secular callings and taken into the Master's work the strength and sterling ..... It is usually a woman who reaches the superlative degree.

Fundamentals: Table of Contents
For many years a data structures course has been taught in computer science ... linked lists) within a set of consecutive storage locations and to describe the ...

Resource Guide: Table of Contents
a university setting; and (3) whether the source presents enough information to be useful ..... of charisma, ideology, community structure and maintenance, recruitment, ...... However, he has an open bias against aspects of the Bahá'í Faith which c

TABLE OF CONTENTS Kindergarten.pdf
There was a problem loading more pages. Retrying... Whoops! There was a problem previewing this document. Retrying... Download. Connect more apps... Try one of the apps below to open or edit this item. TABLE OF CONTENTS Kindergarten.pdf. TABLE OF CON