http://www.stroustrup.com/C++11FAQ.html, https://gcc.gnu.org/projects/cxx-status.html#cxx11 GCC 版本与 C++特性
C++11 - the new ISO C++ standard
Modified August 19, 2016
This document is written by and maintained by Bjarne Stroustrup. Constructive comments, corrections, references, and suggestions are of course most welcome. Currently, I'm working to improve completeness and clean up the references.
Translations:
I have contributed to the new, unified, isocpp.org C++ FAQ maintained by The C++ Foundation of which I am a director. The maintenance of this FAQ is likely to become increasingly sporatic.
C++11 is the ISO C++ standard ratified in 2011. The previous standard is often referred to asC++98 or C++03; the differences between C++98 and C++03 are so few and so technical that they ought not concern users.
A late working paper is available. This is close to the final draft international standard formally accepted by a 21-0 national vote in August 2011.
Before its official ratification, we called the upcoming standard C++0x. I have not had the time to update the name consistently, sorry, and anyway I like the name C++0x :-). The name "C++0x" is a relict of the days where I and others, hoped for a C++08 or C++09. Think of 'x' as hexadecimal (i.e., C++0B == C++11).
All official documents relating to C++11/C++0x can be found at the ISO C++ committee's website. The official name of the committee is SC22 WG21.
Caveat: This FAQ will be under construction for quite a while. Comments, questions, references, corrections, and suggestions welcome.
Purpose
The purpose of this C++11 FAQ is
- To give an overview of the new facilities (language features and standard libraries) offered by C++11 in addition to what is provided by the previous version of the ISO C++ standard.
- To give an idea of the aims of the ISO C++ standards effort.
- To present a user's view of the new facilities
- To provide references to allow for a more in depth study of features.
- To name many of the individuals who contributed (mostly as authors of the reports they wrote for the committee). The standard is not written by a faceless organization.
Please note that the purpose of this FAQ is not to provide comprehensive discussion of individual features or a detailed explanation of how to use them. The aim is to give simple examples to demonstrate what C++11 has to offer (plus references). My ideal is "max one page per feature" independently of how complex a feature is. Details can often be found in the references.
Lists of questions
Here are some high-level questions
- What doyou think of C++11?
- When will C++0x be a formal standard?
- When will compilers implement C++11?
- When will the new standard libraries be available?
- What new language features does C++11 provide? (a list); see alsothe questions below
- What new standard libraries does C++11 provide? (a list); see alsothe questions below
- What were the aims of the C++0x effort?
- What specific design aims guided the committee?
- Where can I find the committee papers?
- Where can I find academic and technical papers about C++11? (a list)
- Where else can I read about C++11? (a list)
- Are there any videos about C++11? (a list)
- Is C++11 hard to learn?
- How does the committee operate?
- Who is on the committee?
- Will there be a C++1y?
- What happened to "concepts?
- Are there any features you don't like?
Questions about individual language features can be found here:
- __cplusplus
- alignments
- attributes
- atomic operations
- auto (type deduction from initializer)
- C99 features
- enum class (scoped and strongly typed enums)
- [[carries_dependency]]
- copying and rethrowing exceptions
- constant expressions (generalized and guaranteed;constexpr)
- decltype
- control of defaults:default and delete
- control of defaults: move and copy
- delegating constructors
- Dynamic Initialization and Destruction with Concurrency
- exception propagation (preventing it;noexcept)
- explicit conversion operators
- extended integer types
- extern templates
- for statement; see range-for statement
- suffix return type syntax (extended function declaration syntax)
- in-class member initializers
- inherited constructors
- initializer lists (uniform and general initialization)
- Inline namespace
- lambdas
- local classes as template arguments
- long long integers (at least 64 bits)
- memory model
- move semantics; see rvalue references
- narrowing (how to prevent it)
- [[noreturn]]
- null pointer (nullptr)
- override controls:override
- override controls:final
- PODs (generalized)
- range-for statement
- raw string literals
- right-angle brackets
- rvalue references
- Simple SFINAE rule
- static (compile-time) assertions (static_assert)
- template alias
- template typedef; see template alias
- thread-local storage (thread_local)
- unicode characters
- Uniform initialization syntax and semantics
- unions (generalized)
- user-defined literals
- variadic templates
I often borrow examples from the proposals. In those cases: Thanks to the proposal authors. Many of the examples are borrowed from my own talks and papers.
Questions about individual standard library facilities can be found here:
- abandoning a process
- Improvements to algorithms
- array
- async()
- atomic operations
- Condition variables
- Improvements to containers
- function and bind
- forward_list a singly-liked list
- future and promise
- garbage collection ABI
- hash_tables; see unordered_map
- metaprogramming and type traits
- Mutual exclusion
- random number generators
- regex a regular expression library
- scoped allocators
- shared_ptr
- smart pointers; see shared_ptr, weak_ptr, and unique_ptr
- threads
- Time utilities
- tuple
- unique_ptr
- unordered_map
- weak_ptr
- system error
Below are answers to specific questions as indexed above.
What do you think of C++11?
That's a (to me) amazingly frequent question. It may be the most frequently asked question. Surprisingly, C++11 feels like a new language: The pieces just fit together better than they used to and I find a higher-level style of programming more natural than before and as efficient as ever. If you timidly approach C++ as just a better C or as an object-oriented language, you are going to miss the point. The abstractions are simply more flexible and affordable than before. Rely on the old mantra: If you think ofit as a separate idea or object, represent it directly in the program; model real-world objects, and abstractions directly in code. It's easier now: Your ideas will map toenumerations, objects, classes (e.g.control of defaults), class hierarchies (e.g.inherited constructors), templates,aliases, exceptions, loops, threads, etc., rather than to a single "one size fits all" abstraction mechanism.
My ideal is to use programming language facilities to help programmers think differently about system design and implementation. I think C++11 can do that - and do it not just for C++ programmers but for programmers used to a variety of modern programming languages in the general and very broad area of systems programming.
In other words, I'm still an optimist.
When will C++11 be a formal standard?
It is now! The first draft for formal comments was produced in September 2008. The Final International Draft standard (FCD) unanimously approved by the ISO C++ committee on March 25, 2011. It was formally approved by a 21-0 national vote in August 2011. The standard was published this year (2011).
Following convention, the new standard is called C++11 (because it was published in 2011). Personally, I prefer plain C++ and to use a year marker only when I need to distinguish it from previous versions of C++, such as ARM C++, C++98 and C++03. For a transition period, I still use C++0x in places. Think of 'x' as hexadecimal.
When will compilers implement C++11?
Currently shipping compilers (e.g. GCC C++, Clang C++,IBM C++, and Microsoft C++) already implement many C++11 features. For example, it seems obvious and popular to ship all or most of the new standard libraries.
I expect more and more features to become available with each new release. I expect to see the first complete C++11 compiler sometime in 2012, but I do not care to guess when such a compiler ships or when every compiler will provide all of C++11. I note that every C++11 feature has already been implemented by someone somewhere so there is implementation experience available for implementers to rely on.
Here are links to C++11 information from purveyors:
When will the new standard libraries be available?
Initial versions of the new standard libraries are currently shipping with the GCC,Clang and Microsoft implementations, and are available fromboost.
What new language features does C++11 provide?
You don't improve a language by simply adding every feature that someone considers a good idea. In fact, essentially every feature of most modern languages has been suggested to me for C++ by someone: Try to imagine what the superset of C99, C#, Java, Haskell, Lisp, Python, and Ada would look like. To make the problem more difficult, remember that it is not feasible to eliminate older features, even if the committee agrees that they are bad: experience shows that users force every implementer to keep providing deprecated and banned features under compatibility switches (or by default) for decades.
To try to select rationally from the flood of suggestions we devised a set of specific design aims. We couldn't completely follow them and they weren't sufficiently complete to guide the committee in every detail (and IMO couldn't possible be that complete).
The result has been a language with greatly improved abstraction mechanisms. The range of abstractions that C++ can express elegantly, flexibly, and at zero costs compared to hand-crafted specialized code has greatly increased. When we say "abstraction" people often just think "classes" or "objects." C++11 goes far beyond that: The range of user-defined types that can be cleanly and safely expressed has grown with the addition of features such asinitializer-lists,uniform initialization,template aliases, rvalue references, defaulted and deleted functions, and variadic templates. Their implementation eased with features, such as auto, inherited constructors, and decltype. These enhancements are sufficient to make C++11 feel like a new language.
For a list of accepted language features, see the feature list
What new standard libraries does C++11 provide?
I would have liked to see more standard libraries. However, note that the standard library definition is already about 70% of the normative text of the standard (and that doesn't count the C standard library, which is included by reference). Even though some of us would have liked to see many more standard libraries, nobody could claim that the Library working group has been lazy. It is also worth noting that the C++98 libraries have been significantly improved through the use of new language features, such as initializer-lists,rvalue references,variadic templates, noexcept, and constexpr. The C++11 standard library is easier to use and provides better performance that the C++98 one.
For a list of accepted libraries, see the library component list.
What were the aims of the C++11 effort?
C++ is a general-purpose programming language with a bias towards systems programming that
- is a better C
- supports data abstraction
- supports object-oriented programming
- supports generic programming
The overall aims of the C++11 effort was to strengthen that:
- Make C++ a better language for systems programming and library building -- that is, to build directly on C++'s contributions to programming, rather than providing specialized facilities for a particular sub-community (e.g. numeric computation or Windows-style application development).
- Make C++ easier to teach and learn -- through increased uniformity, stronger guarantees, and facilities supportive of novices (there will always be more novices than experts).
Naturally, this is done under very stringent compatibility constraints. Only very rarely is the committee willing to break standards conforming code, though that's done when a new keyword (e.g.static_assert,nullptr, andconstexpr) is introduced.
For more details see:
- B. Stroustrup: What is C++11?. CVu. Vol 21, Issues 4 and 5. 2009.
- B. Stroustrup: Evolving a language in and for the real world: C++ 1991-2006. ACM HOPL-III. June 2007.
- B. Stroustrup: A History of C++: 1979-1991. Proc ACM History of Programming Languages conference (HOPL-2). March 1993.
- B. Stroustrup: C and C++: Siblings. The C/C++ Users Journal. July 2002.
What specific design aims guided the committee?
Naturally, different people and different organizations involved with the standardization have somewhat different aims, especially when it comes to details and to priorities. Also, detailed aims change over time. Please remember that the committee can't even do all that everyone agrees would be good things -- it consists of volunteers with very limited resources. However, here are a set of criteria that has seen real use in the discussion of which features and libraries were appropriate for C++11:
- Maintain stability and compatibility -- don't break old code, and if you absolutely must, don't break it quietly.
- Prefer libraries to language extensions -- an ideal at which the committee wasn't all that successful; too many people in the committee and elsewhere prefer "real language features."
- Prefer generality to specialization -- focus on improving the abstraction mechanisms (classes, templates, etc.).
- Support both experts and novices -- novices can be helped by better libraries and through more general rules; experts need general and efficient features.
- Increase type safety -- primarily though facilities that allow programmers to avoid type-unsafe features.
- Improve performance and ability to work directly with hardware -- make C++ even better for embedded systems programming and high-performance computation.
- Fit into the real world -- consider tool chains, implementation cost, transition problems, ABI issues, teaching and learning, etc.
Note that integrating features (new and old) to work in combination is the key -- and most of the work. The whole is much more than the simple sum of its parts.
Another way of looking at detailed aims is to look at areas of use and styles of usage:
- Machine model and concurrency -- provide stronger guarantees for and better facilities for using modern hardware (e.g. multicores and weakly coherent memory models). Examples are thethread ABI,futures,thread-local storage, and theatomics ABI.
- Generic programming -- GP is among the great success stories of C++98; we needed to improve support for it based on experience. Examples areauto andtemplate aliases.
- Systems programming -- improve the support for close-to-the-hardware programming (e.g. low-level embedded systems programming) and efficiency. Examples areconstexpr,std::array, andgeneralized PODs.
- Library building -- remove limitations, inefficiencies, and irregularities from the abstraction mechanisms. Examples areinline namespace, inherited constructors, and rvalue references.
Where can I find the committee papers?
Go to the papers section of the committee's website. There you will most likely drown in details. Look for "issues lists" and "State of " (e.g.State of Evolution (July 2008)) lists. The key groups are
- Core (CWG) -- dealing with language-technical issues and formulation
- Evolution (EWG) -- dealing with language feature proposals and issues crossing the language/library boundary
- Library (LWG) -- dealing with library facility proposals
Here is the latest draft C++11 standard.
Where can I find academic and technical papers about C++11?
- Bjarne Stroustrup: Software Development for Infrastructure. Computer, vol. 45, no. 1, pp. 47-58, Jan. 2012, doi:10.1109/MC.2011.353.A video interview about that paper andvideo of a talk on a very similar topic (That's a 90 minute talk incl. Q&A).
- Saeed Amrollahi: Modern Programming in the New Millenium: A Technical Survey on Outstanding features of C++0x. Computer Report (Gozaresh-e Computer), No.199, November 2011 (Mehr and Aban 1390), pages 60-82. (in Persian)
- Mark Batty et al's: Mathematizing C++ concurrency, POPL 2012. // thorough, precise, and mathematical.
- Gabriel Dos Reis and Bjarne Stroustrup: General Constant Expressions for System Programming Languages. SAC-2010. The 25th ACM Symposium On Applied Computing.
- Hans-J. Boehm and Sarita V. Adve: Foundations of the C++ concurrency memory model. ACM PLDI'08.
- Hans-J. Boehm: Threads Basic. HPL technical report 2009-259 // ``what every programmer should know about memory model issues''
- Douglas Gregor, Jaakko Jarvi, Jeremy Siek, Bjarne Stroustrup, Gabriel Dos Reis, and Andrew Lumsdaine:Concepts: Linguistic Support for Generic Programming in C++. OOPSLA'06, October 2006. // The concept design and implementation as it stood in 2006; it has improved since,though not sufficiently to save it.
- Douglas Gregor and Jaakko Jarvi: Variadic templates for C++0x. Journal of Object Technology, 7(2):31-51, February 2008.
- Jaakko Jarvi and John Freeman: Lambda functions for C++0x. ACM SAC '08.
- Jaakko Jarvi, Mat Marcus, and Jacob N. Smith: Programming with C++ Concepts. Science of Computer Programming, 2008. To appear.
- M. Paterno and W. E. Brown : Improving Standard C++ for the Physics Community. CHEP'04. // Much have been improved since then!
- Michael Spertus and Hans J. Boehm: The Status of Garbage Collection in C++0X. ACM ISMM'09.
- Verity Stob: An unthinking programmer's guide to the new C++ -- Raising the standard. The Register. May 2009. (Humor (I hope)).
- [N1781=05-0041] Bjarne Stroustrup: Rules of thumb for the design of C++0x.
- Bjarne Stroustrup:Evolving a language in and for the real world: C++ 1991-2006. ACM HOPL-III. June 2007. (incl. slides and videos). // Covers the design aims of C++0x, the standards process, and the progress up until 2007.
- B. Stroustrup: What is C++0x?. CVu. Vol 21, Issues 4 and 5. 2009.
- Anthony Williams: Simpler Multithreading in C++0x. devx.com.
This list is likely to be incomplete -- and likely to frequently go out of date as people write new papers. If you find a paper that ought to be here and is not, please send it. Also, not all papers will be completely up-to-date with the latest improvements of the standard. I'll try to keep comments current.
Where else can I read about C++11?
The amount of information about C++11 is increasing as the standard nears completion and C++ implementations start providing new language features and libraries. Here is a short list of sources:
- B. Stroustrup: The C++ Programming Language (Fourth Edition).
- the papers section of the committee's website.
- C++11 draft.
- the C++11 Wikipedia entry. Seems to be actively maintained, though apparently not by members of the committee.
- A list of support for C++11 features.
Are there any videos about C++11?
(To people who know me, this is a proof that this really is an FAQ, rather than a series of my own favorite questions; I'm not a fan of videos on technical topics -- I find the video distracting and the verbal format too likely to contain minor technical errors).
Yes:
- B. Stroustrup, H. Sutter, H-J. Boehm, A. Alexandrescu, S.T.Lavavej, Chandler Carruth, Andrew Sutter, and more: several talks and panels from theGoing Native 2012 conference.
- B. Stroustrup, H. Sutter, Sean Parent, Scott Meyers, and more: several talks and panels from theGoing Native 2013 conference.
- Herb Sutter: Writing modern C++ code: how C++ has evolved over the years. September 2011.
- Herb Sutter: C++ and Beyond 2011: Herb Sutter - Why C++?. August 2011.
- Try Google videos.
- Lawrence Crowl: Lawrence Crowl on C++ Threads. in Sophia Antipolis, June 2008.
- Bjarne Stroustrup: The design of C++0x at U of Waterloo in 2007.
- Bjarne Stroustrup: Initialization at Google in 2007.
- Bjarne Stroustrup: C++0x -- An overview. in Sophia Antipolis, June 2008.
- Lawrence Crowl: Threads.
- Roger Orr: C++0x. January 2008.
- Hans-Jurgen Boehm: Getting C++ Threads Right. December 2007.
Is C++11 hard to learn?
Well, since we can't remove any significant features from C++ without breaking large amounts of code, C++11 is larger than C++98, so if you want to know every rule, learning C++11 will be harder. This leaves us with just two tools for simplification (from the point of view of learners):
- Generalization: Replace, say, three rules with one more general rule (e.g., uniform initialization, inheriting constructors, and threads).
- Simpler alternatives: Provide new facilities that are easier to use than their older alternatives (e.g., thearray,auto, range-for statement, and regex).
Obviously, a "bottom up" teaching/learning style will nullify any such advantage, and there are currently (obviously) very little material that takes a different approach. That ought to change with time.
How does the committee operate?
The ISO Standards committee, SC22 WG21, operates under the ISO rules for such committees. Curiously enough, these rules are not standardized and change over time.
Many countries have national standards bodies with active C++ groups. These groups hold meetings, coordinate over the web, and some send representatives to the ISO meetings. Canada, France, Germany, Switzerland, UK, and USA are present at most meetings. Denmark, the Netherlands, Japan, Norway, Spain, and others are represented in person less frequently.
Much of the work goes on in-between meetings over the web and the results are recorded as numbered committee papers on theWG21 website.
The committee meets two to three times a year for a week each time. Most work at those meetings are in sub-working groups, such as "Core", "Library", "Evolution", and "Concurrency." As needed, there are also in-between meetings of ad-hoc working groups on specific urgent topics, such as "concepts" and "memory model." Voting takes place at the main meetings. First, working groups hold "straw votes" to see if an issue is ready for presentation to the committee as a whole. Then, the committee as a whole votes (one member one vote) and if something is accepted the nations vote. We take great care that we do not get into a situation where the majority present and the nations disagrees -- proceeding if that is the case would guarantee long-term controversy. Final votes on official drafts are done by mail by the national standards bodies.
The committee has formal liaison with the C standards group (SC22 WG14) and POSIX, and more or less formal contacts with several other groups.
Who is on the committee?
The committee consists of a large number of people (about 250) out of whom 90+ turn up at the week-long meetings two or three times a year. In addition there are national standards groups and meetings in several countries. Most members contribute either by attending meetings, by taking part in email discussions, or by submitting papers for committee consideration. Most members have friends and colleagues who help them. From day #1, the committee has had members from many countries and at every meeting people from half a dozen to a dozen countries attend. The final votes are done by about 20 national standards bodies. Thus, the ISO C++ standardization is a fairly massive effort,not a small coherent group of people working to create a perfect language for "people just like themselves." The standard is what this group of volunteers can agree on as being the best they can produce thatall can live with.
Naturally, many (but not all) of these volunteers have day jobs focused on C++: We have compiler writers, tool builders, library writers, application builders (too few of those), researchers (only a few), consultants, test-suite builders, and more.
Here is a very abbreviated list of organizations involved: Adobe, Apple, Boost, Bloomberg, EDG, Google, HP, IBM, Intel, Microsoft, Red Hat, Sun.
Here is a short list of names of members who you may have encountered in the literature or on the web:Dave Abrahams, Matt Austern,Pete Becker, Hans Boehm, Steve Clamage, Lawrence Crowl,Beman Dawes,Francis Glassborow,Doug Gregor, Pablo Halpern, Howard Hinnant, Jaakko Jarvi,John Lakos, Alisdair Meredith, Jens Maurer, Jason Merrill,Sean Parent, P.J. Plauger, Tom Plum, Gabriel Dos Reis,Bjarne Stroustrup,Herb Sutter,David Vandevoorde, Michael Wong. Apologies to the 200+ current and past members that I couldn't list. Also, please note the author lists on the various papers: a standard is written by (many) individuals, not by an anonymous committee.
You can get a better impression of the breath and depth of expertise involved by examining the author lists on theWG21 papers, but please remember there are major contributors to the standards effort who do not write a lot.
Will there be a C++1y?
Almost certainly -- and not just because the committee has slipped the deadline for C++0x. The plans for minor revisions, C++14, are well advanced (the features have been voted into the working draft and implemented), and the plan is for a major revision in 2017, C++17.
What happened to "concepts"?
"Concepts" was a feature designed to allow precise specification of requirements on template arguments. Unfortunately, the committee decided that further work on concepts could seriously delay the standard and voted to remove the feature from the working paper, see my note The C++0x "Remove Concepts" Decision andA DevX interview on concepts and the implications for C++0x for an explanation.
A radically simplified version ``concepts lite'' will be part of C++14 (as a technical report).
I have not deleted the concept sections from this document, but left them at the end:
- axioms (semantic assumptions)
- concepts
- concept maps
Are there any features you don't like?
Yes. There are also features in C++98 that I don't like, such as macros. The issue is not whether I like something or if I find it useful for something I want to do. The issue is whether someone has felt enough of a need to convince others to support the idea or possibly if some usage is so ingrained in a user community that it needs support.
__cplusplus
In C++11 the macro __cplusplus will be set to a value that differs from (is greater than) the current199711L.
auto -- deduction of a type from an initializer
Consider
auto x = 7;
Here x will have the type int because that's the type of its initializer. In general, we can write
auto x = expression;
and the type of x will be the type of the value computed from "expression".
The use of auto to deduce the type of a variable from its initializer is obviously most useful when that type is either hard to know exactly or hard to write. Consider:
template<class T> void printall(const vector<T>& v) { for (auto p = v.begin(); p!=v.end(); ++p) cout << *p << "\n"; }
In C++98, we'd have to write
template<class T> void printall(const vector<T>& v) { for (typename vector<T>::const_iterator p = v.begin(); p!=v.end(); ++p) cout << *p << "\n"; }
When the type of a variable depends critically on template argument it can be really hard to write code withoutauto. For example:
template<class T, class U> void multiply(const vector<T>& vt, const vector<U>& vu) { // ... auto tmp = vt[i]*vu[i]; // ... }
The type of tmp should be what you get from multiplying a T by a U, but exactly what that is can be hard for the human reader to figure out, but of course the compiler knows once it has figured out what particularT and U it is dealing with.
The auto feature has the distinction to be the earliest to be suggested and implemented: I had it working in my Cfront implementation in early 1984, but was forced to take it out because of C compatibility problems. Those compatibility problems disappeared when C++98 and C99 accepted the removal of "implicit int"; that is, both languages require every variable and function to be defined with an explicit type. The old meaning ofauto ("this is a local variable") is now illegal. Several committee members trawled through millions of lines of code finding only a handful of uses -- and most of those were in test suites or appeared to be bugs.
Being primarily a facility to simplify notation in code, auto does not affect the standard library specification.
See also
- the C++ draft section 7.1.6.2, 7.1.6.4, 8.3.5 (for return types)
- [N1984=06-0054] Jaakko Jarvi, Bjarne Stroustrup, and Gabriel Dos Reis: Deducing the type of variable from its initializer expression (revision 4).
Range-for statement
A range for statement allows you to iterate through a "range", which is anything you can iterate through like an STL-sequence defined by a begin() and end(). All standard containers can be used as a range, as can a std::string, an initializer list, an array, and anything for which you define begin() and end(), e.g. an istream. For example:
void f(vector<double>& v) { for (auto x : v) cout << x << '\n'; for (auto& x : v) ++x; // using a reference to allow us to change the value }
You can read that as "for all x in v" going through starting with v.begin() and iterating to v.end(). Another example:
for (const auto x : { 1,2,3,5,8,13,21,34 }) cout << x << '\n';
The begin() (and end()) can be a member to be calledx.begin() or a free-standing function to be called begin(x). The member version takes precedence.
See also
- the C++ draft section 6.5.4 (note: changed not to use concepts)
- [N2243==07-0103] Thorsten Ottosen: Wording for range-based for-loop (revision 2).
- [N3257=11-0027 ] Jonathan Wakely and Bjarne Stroustrup: Range-based for statements and ADL (Option 5 was chosen).
right-angle brackets
Consider
list<vector<string>> lvs;
In C++98 this is a syntax error because there is no space between the two >s. C++11 recognizes such two>s as a correct termination of two template argument lists.
Why was this ever a problem? A compiler front-end is organized parses/stages. This is about the simplest model:
- lexical analysis (make up tokens from characters)
- syntax analysis (check the grammar)
- type checking (find the type of names and expressions)
These stages are in theory and sometimes in practice strictly separate, so the lexical analyzer that determines that>> is a token (usually meaning right-shift or input) has no idea of its meaning; in particular, it has no idea of templates or nested template argument lists. However, to get that example "correct" the three stages has somehow to cooperate. The key observation that led to the problem being resolved was that every C++ compiler already did understand the problem so that it could give decent error messages.
See also
- the C++ draft section ???
- [N1757==05-0017] Daveed Vandevoorde: revised right angle brackets proposal (revision 2).
control of defaults: default and delete
The common idiom of "prohibiting copying" can now be expressed directly:
class X { // ... X& operator=(const X&) = delete; // Disallow copying X(const X&) = delete; };
Conversely, we can also say explicitly that we want to default copy behavior:
class Y { // ... Y& operator=(const Y&) = default; // default copy semantics Y(const Y&) = default; };
Being explicit about the default is redundant. However, comments about copy operations and (worse) a user explicitly defining copy operations meant to give the default behavior are not uncommon. Leaving it to the compiler to implement the default behavior is simpler, less error-prone, and often leads to better object code.
The "default" mechanism can be used for any function that has a default. The "delete" mechanism can be used for any function. For example, we can eliminate an undesired conversion like this:
struct Z { // ... Z(long long); // can initialize with an long long Z(long) = delete; // but not anything less };
See also
- the C++ draft section ???
- [N1717==04-0157] Francis Glassborow and Lois Goldthwaite: explicit class and default definitions (an early proposal).
- Bjarne Stroustrup: Control of class defaults (a dead end).
- [N2326==07-0186] Lawrence Crowl: Defaulted and Deleted Functions.
- [N3174=100164] B. Stroustrup: To move or not to move. An analysis of problems related to generated copy and move operations. Approved.
control of defaults: move and copy
By default, a class has 5 operations:
- copy assignment
- copy constructor
- move assignment
- move constructor
- destructor
If you declare any of those you must consider all and explicitly define or default the ones you want. Think of copying, moving, and destruction as closely related operations, rather than individual operations that you can freely mix and match - you can specify arbitrary combinations, but only a few combinations make sense semantically.
If any move, copy, or destructor is explicitly specified (declared, defined, =default, or =delete) by the user, no move is generated by default. If any move, copy, or destructor is explicitly specified (declared, defined, =default, or =delete) by the user, any undeclared copy operations are generated by default, but this is deprecated, so don't rely on that. For example:
class X1 { X1& operator=(const X1&) = delete; // Disallow copying };
This implicitly also disallows moving of X1s. Copy initialization is allowed, but deprecated.
class X2 { X2& operator=(const X2&) = delete; };
This implicitly also disallows moving of X2s. Copy initialization is allowed, but deprecated.
class X3 { X3& operator=(X3&&) = delete; // Disallow moving };
This implicitly also disallows copying of X3s.
class X4 { ~X4() = delete; // Disallow destruction };
This implicitly also disallows moving of X4s. Copying is allowed, but deprecated.
I strongly recommend that if you declare one of these five function, you explicitly declare all. For example:
template<class T> class Handle { T* p; public: Handle(T* pp) : p{pp} {} ~Handle() { delete p; } // user-defined destructor: no implicit copy or move Handle(Handle&& h) :p{h.p} { h.p=nullptr; } // transfer ownership Handle& operator=(Handle&& h) { delete p; p=h.p; h.p=nullptr; return *this; } // transfer ownership Handle(const Handle&) = delete; // no copy Handle& operator=(const Handle&) = delete; // ... };
See also
- the C++ draft section ???
- [N2326==07-0186] Lawrence Crowl: Defaulted and Deleted Functions.
- [N3174=100164] B. Stroustrup: To move or not to move. An analysis of problems related to generated copy and move operations. Approved.
enum class -- scoped and strongly typed enums
The enum classes ("new enums", "strong enums") address three problems with traditional C++ enumerations:
- conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
- conventional enums export their enumerators to the surrounding scope, causing name clashes.
- the underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.
enum classs ("strong enums") are strongly typed and scoped:
enum Alert { green, yellow, orange, red }; // traditional enum enum class Color { red, blue }; // scoped and strongly typed enum // no export of enumerator names into enclosing scope // no implicit conversion to int enum class TrafficLight { red, yellow, green }; Alert a = 7; // error (as ever in C++) Color c = 7; // error: no int->Color conversion int a2 = red; // ok: Alert->int conversion int a3 = Alert::red; // error in C++98; ok in C++11 int a4 = blue; // error: blue not in scope int a5 = Color::blue; // error: not Color->int conversion Color a6 = Color::blue; // ok
As shown, traditional enums work as usual, but you can now optionally qualify with theenum's name.
The new enums are "enum class" because they combine aspects of traditional enumerations (names values) with aspects of classes (scoped members and absence of conversions).
Being able to specify the underlying type allow simpler interoperability and guaranteed sizes of enumerations:
enum class Color : char { red, blue }; // compact representation enum class TrafficLight { red, yellow, green }; // by default, the underlying type is int enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U }; // how big is an E? // (whatever the old rules say; // i.e. "implementation defined") enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U }; // now we can be specific
It also enables forward declaration of enums:
enum class Color_code : char; // (forward) declaration void foobar(Color_code* p); // use of forward declaration // ... enum class Color_code : char { red, yellow, green, blue }; // definition
The underlying type must be one of the signed or unsigned integer types; the default isint.
In the standard library, enum classes are used
- For mapping systems specific error codes: In <system_error>: enum class errc;
- For pointer safety indicators: In <memory>: enum class pointer_safety { relaxed, preferred, strict };
- For I/O stream errors: In <iosfwd>: enum class io_errc { stream = 1 };
- For asynchronous communications error handling: In <future>: enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
Several of these have operators, such as == defined.
See also
- the C++ draft section 7.2
- [N1513=03-0096] David E. Miller: Improving Enumeration Types (original enum proposal).
- [N2347 = J16/07-0207] David E. Miller, Herb Sutter, and Bjarne Stroustrup: Strongly Typed Enums (revision 3).
- [N2499=08-0009] Alberto Ganesh Barbati: Forward declaration of enumerations.
constexpr -- generalized and guaranteed constant expressions
The constexpr mechanism
- provides more general constant expressions
- allows constant expressions involving user-defined types
- provides a way to guarantee that an initialization is done at compile time
Consider
enum Flags { good=0, fail=1, bad=2, eof=4 }; constexpr int operator|(Flags f1, Flags f2) { return Flags(int(f1)|int(f2)); } void f(Flags x) { switch (x) { case bad: /* ... */ break; case eof: /* ... */ break; case bad|eof: /* ... */ break; default: /* ... */ break; } }
Here constexpr says that the function must be of a simple form so that it can be evaluated at compile time if given constant expressions arguments.
In addition to be able to evaluate expressions at compile time, we want to be able torequire expressions to be evaluated at compile time; constexpr in front of a variable definition does that (and impliesconst):
constexpr int x1 = bad|eof; // ok void f(Flags f3) { constexpr int x2 = bad|f3; // error: can't evaluate at compile time int x3 = bad|f3; // ok }
Typically we want the compile-time evaluation guarantee for global or namespace objects, often for objects we want to place in read-only storage.
This also works for objects for which the constructors are simple enough to beconstexpr and expressions involving such objects:
struct Point { int x,y; constexpr Point(int xx, int yy) : x(xx), y(yy) { } }; constexpr Point origo(0,0); constexpr int z = origo.x; constexpr Point a[] = {Point(0,0), Point(1,1), Point(2,2) }; constexpr int x = a[1].x; // x becomes 1
Please note that constexpr is not a general purpose replacement forconst (or vise versa):
- const's primary function is to express the idea that an object is not modified through an interface (even though the object may very well be modified through other interfaces). It just so happens that declaring an objectconst provides excellent optimization opportunities for the compiler. In particular, if an object is declaredconst and its address isn't taken, a compiler is often able to evaluate its initializer at compile time (though that's not guaranteed) and keep that object in its tables rather than emitting it into the generated code.
- constexpr's primary function is to extend the range of what can be computed at compile time, making such computation type safe. Objects declaredconstexpr have their initializer evaluated at compile time; they are basically values kept in the compiler's tables and only emitted into the generated code if needed.
See also
- the C++ draft 3.6.2 Initialization of non-local objects, 3.9 Types [12], 5.19 Constant expressions, 7.1.5 The constexpr specifier
- [N1521=03-0104] Gabriel Dos Reis: Generalized Constant Expressions (original proposal).
- [N2235=07-0095] Gabriel Dos Reis, Bjarne Stroustrup, and Jens Maurer: Generalized Constant Expressions -- Revision 5.
decltype -- the type of an expression
decltype(E) is the type ("declared type") of the name or expressionE and can be used in declarations. For example:
void f(const vector<int>& a, vector<float>& b) { typedef decltype(a[0]*b[0]) Tmp; for (int i=0; i<b.size(); ++i) { Tmp* p = new Tmp(a[i]*b[i]); // ... } // ... }
This notion has been popular in generic programming under the label "typeof" for a long time, but thetypeof implementations in actual use were incomplete and incompatible, so the standard version is nameddecltype.
If you just need the type for a variable that you are about to initialize auto is often a simpler choice. You really need decltype if you need a type for something that is not a variable, such as areturn type.
See also
- the C++ draft 7.1.6.2 Simple type specifiers
- [Str02] Bjarne Stroustrup. Draft proposal for "typeof". C++ reflector message c++std-ext-5364, October 2002. (original suggestion).
- [N1478=03-0061] Jaakko Jarvi, Bjarne Stroustrup, Douglas Gregor, and Jeremy Siek:Decltype and auto (original proposal).
- [N2343=07-0203] Jaakko Jarvi, Bjarne Stroustrup, and Gabriel Dos Reis: Decltype (revision 7): proposed wording.
Initializer lists
Consider
vector<double> v = { 1, 2, 3.456, 99.99 }; list<pair<string,string>> languages = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} }; map<vector<string>,vector<int>> years = { { {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} }, { {"Martin", "Ritchards"}, {1982, 2003, 2007} }, { {"David", "John", "Wheeler"}, {1927, 1947, 1951, 2004} } };
Initializer lists are not just for arrays any more. The mechanism for accepting a{}-list is a function (often a constructor) accepting an argument of typestd::initializer_list<T>. For example:
void f(initializer_list<int>); f({1,2}); f({23,345,4567,56789}); f({}); // the empty list f{1,2}; // error: function call ( ) missing years.insert({{"Bjarne","Stroustrup"},{1950, 1975, 1985}});
The initializer list can be of arbitrary length, but must be homogeneous (all elements must be of a the template argument type,T, or convertible to T).
A container might implement an initializer-list constructor like this:
template<class E> class vector { public: vector (std::initializer_list<E> s) // initializer-list constructor { reserve(s.size()); // get the right amount of space uninitialized_copy(s.begin(), s.end(), elem); // initialize elements (in elem[0:s.size())) sz = s.size(); // set vector size } // ... as before ... };
The distinction between direct initialization and copy initialization is maintained for{}-initialization, but becomes relevant less frequently because of{}-initialization. For example, std::vector has anexplicit constructor from int and an initializer-list constructor:
vector<double> v1(7); // ok: v1 has 7 elements v1 = 9; // error: no conversion from int to vector vector<double> v2 = 9; // error: no conversion from int to vector void f(const vector<double>&); f(9); // error: no conversion from int to vector vector<double> v1{7}; // ok: v1 has 1 element (with its value 7.0) v1 = {9}; // ok v1 now has 1 element (with its value 9.0) vector<double> v2 = {9}; // ok: v2 has 1 element (with its value 9.0) f({9}); // ok: f is called with the list { 9 } vector<vector<double>> vs = { vector<double>(10), // ok: explicit construction (10 elements) vector<double>{10}, // ok: explicit construction (1 element with the value 10.0) 10 // error: vector's constructor is explicit };
The function can access the initializer_list as an immutable sequence. For example:
void f(initializer_list<int> args) { for (auto p=args.begin(); p!=args.end(); ++p) cout << *p << "\n"; }
A constructor that takes a single argument of type std::initializer_list is called an initializer-list constructor.
The standard library containers, string, and regex have initializer-list constructors, assignment, etc. An initializer-list can be used as a range, e.g. in arange for statement
The initializer lists are part of the scheme for uniform and general initialization.
See also
- the C++ draft 8.5.4 List-initialization [dcl.init.list]
- [N1890=05-0150 ] Bjarne Stroustrup and Gabriel Dos Reis: Initialization and initializers (an overview of initialization-related problems with suggested solutions).
- [N1919=05-0179] Bjarne Stroustrup and Gabriel Dos Reis: Initializer lists.
- [N2215=07-0075] Bjarne Stroustrup and Gabriel Dos Reis : Initializer lists (Rev. 3) .
- [N2640=08-0150] Jason Merrill and Daveed Vandevoorde: Initializer Lists -- Alternative Mechanism and Rationale (v. 2) (final proposal).
Preventing narrowing
The problem: C and C++ implicitly truncates:
int x = 7.3; // Ouch! void f(int); f(7.3); // Ouch!
However, in C++11, {} initialization doesn't narrow:
int x0 {7.3}; // error: narrowing int x1 = {7.3}; // error: narrowing double d = 7; int x2{d}; // error: narrowing (double to int) char x3{7}; // ok: even though 7 is an int, this is not narrowing vector<int> vi = { 1, 2.3, 4, 5.6 }; // error: double to int narrowing
The way C++11 avoids a lot of incompatibilities is by relying on the actual values of initializers (such as 7 in the example above) when it can (and not just type) when deciding what is a narrowing conversion. If a value can be represented exactly as the target type, the conversion is not narrowing.
char c1{7}; // OK: 7 is an int, but it fits in a char char c2{77777}; // error: narrowing (assuming 8-bit chars)
Note that floating-point to integer conversions are always considered narrowing -- even 7.0 to 7.
See also
- the C++ draft section 8.5.4.
- [N1890=05-0150 ] Bjarne Stroustrup and Gabriel Dos Reis: Initialization and initializers (an overview of initialization-related problems with suggested solutions).
- [N2215=07-0075] Bjarne Stroustrup and Gabriel Dos Reis : Initializer lists (Rev. 3) .
- [N2640=08-0150] Jason Merrill and Daveed Vandevoorde: Initializer Lists - Alternative Mechanism and Rationale (v. 2) (primarily on "explicit").
Delegating constructors
In C++98, if you want two constructors to do the same thing, repeat yourself or call "an init() function." For example:
class X { int a; void validate(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); } public: X(int x) { validate(x); } X() { validate(42); } X(string s) { int x = lexical_cast<int>(s); validate(x); } // ... };
Verbosity hinders readability and repetition is error-prone. Both get in the way of maintainability. So, in C++11, we can define one constructor in terms of another:
class X { int a; public: X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); } X() :X{42} { } X(string s) :X{lexical_cast<int>(s)} { } // ... };
See also
- the C++ draft section 12.6.2
- N1986==06-0056 Herb Sutter and Francis Glassborow: Delegating Constructors (revision 3).
In-class member initializers
In C++98, only static const members of integral types can be initialized in-class, and the initializer has to be a constant expression. These restrictions ensure that we can do the initialization at compile-time. For example:
int var = 7; class X { static const int m1 = 7; // ok const int m2 = 7; // error: not static static int m3 = 7; // error: not const static const int m4 = var; // error: initializer not constant expression static const string m5 = "odd"; // error: not integral type // ... };
The basic idea for C++11 is to allow a non-static data member to be initialized where it is declared (in its class). A constructor can then use the initializer when run-time initialization is needed. Consider:
class A { public: int a = 7; };
This is equivalent to:
class A { public: int a; A() : a(7) {} };
This saves a bit of typing, but the real benefits come in classes with multiple constructors. Often, all constructors use a common initializer for a member:
class A { public: A(): a(7), b(5), hash_algorithm("MD5"), s("Constructor r