+ All Categories
Home > Documents > 5147 c++0 Special Report Op

5147 c++0 Special Report Op

Date post: 10-Apr-2018
Category:
Upload: amidamaru-rookie
View: 235 times
Download: 0 times
Share this document with a friend

of 42

Transcript
  • 8/8/2019 5147 c++0 Special Report Op

    1/42

    C++Ox:The Dawning of a New Standard

    Special Report Bundle

  • 8/8/2019 5147 c++0 Special Report Op

    2/42

    Contents

    C++0x: The Dawning of a New StandardIt's been 10 years since the first ISO C++ standard, and 2009 will bring us the second. In this special

    report, DevX delves into the new features being discussed by the standards team. Learn how these

    new features will revolutionize the way you code.

    Overview: C++ Gets an OverhaulIt's been 10 years since the first ISO C++ standard, and 2009 will bring us the second.Learn about the new features being added and how they will revolutionize the language.

    Easier C++: An Introduction to ConceptsC++0x concepts bring the full power of the Generic Programming paradigm to C++,

    making templates more expressive, easier to write, and easier to use. Spectacularly poor

    template error messages are a thing of the past!

    Simpler Multithreading in C++0x

    The new standard will support multithreading, with a new thread library. Find out how thiswill improve porting code, and reduce the number of APIs and syntaxes you use.

    The State of the Language: An Interview with Bjarne StroustrupC++ founding father assesses the language on the eve of its new standard.

    Timeline: C++ in RetrospectFrom its nascent pre-processor in 1979 to today's incredibly sophisticated language

    features and libraries, we've documented each step along the way.

  • 8/8/2019 5147 c++0 Special Report Op

    3/42

    Overview: C++ Gets an Overhaul

    C++0x:The Dawning of a New Standard

  • 8/8/2019 5147 c++0 Special Report Op

    4/42

    Overview: C++ Gets an Overhaul

    Originally from http://www.devx.com/SpecialReports/Article/38884

    Overview: C++ Gets an OverhaulIn this overview of the changes proposed for the new standard, you'll get an idea of

    the kinds of improvements you can expect this time around.by Danny Kalev

    en years after the ratification of the first ISO C++ standard, C++ is heading for no less than arevolution. C++0x, the new C++ standard due in 2009, brings a new spirit and new flesh into the

    software development world. Brace yourself for state-of-the-art design idioms, even better

    performance, and a plethora of new features such as multithreading, concepts, hash table, rvalue

    references, smarter smart pointers, and new algorithms. No doubt you'll find a lot to like in C++0x!

    New Core Features

    The two most important features of C++0x are concepts and concurrency support. Conceptsenable programmers to specify constraints on template parameters, thus making generic

    programming and design immensely simpler and more reliable (see Douglas Gregor's excellent

    introduction to concepts). Variadic templates, template aliases (also called template typedefs), and

    static_assertthough not directly related to conceptswill also make the use of templates in genericlibraries more intuitive, flexible, and less error prone.

    The importance of a standardized concurrency APIin C++ can't be overstated: As multicore

    processors are becoming widespread, you simply can't afford to remain stuck in the single-

    threaded era, or compromise on platform-dependent APIs. At last, there's a portable, standardized

    and efficient multithreading library for C++. To get a glimpse of the new concurrency facilities of C++0x, you're welcome to read Anthony Williams' brilliant introduction to multithreading in C++0x.

    You can find additional info about thread-local storage here.

    Rvalue references are yet another silent revolution. While most users will probably not even know

    they exist (read my interview with Bjarne Stroustrup), rvalue references enable library designers to

    optimize containers and algorithms by implementing move semantics and perfect forwarding

    easily, thus reducing unneeded copy operations.

    C++Ox:The Dawning of a New Standard

    http://www.devx.com/SpecialReports/Article/38884http://www.devx.com/SpecialReports/Article/38864http://www.devx.com/SpecialReports/Article/38864http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2191.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1406.pdfhttp://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=343http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=343http://www.devx.com/SpecialReports/Article/38883http://www.devx.com/cplus/10%20Minute%20Solution/37436/0http://www.devx.com/SpecialReports/Article/38813http://www.devx.com/cplus/10%20Minute%20Solution/34577/0http://www.devx.com/cplus/10%20Minute%20Solution/34577/0http://www.devx.com/SpecialReports/Article/38813http://www.devx.com/cplus/10%20Minute%20Solution/37436/0http://www.devx.com/SpecialReports/Article/38883http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=343http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1406.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2191.pdfhttp://www.devx.com/SpecialReports/Article/38864http://www.devx.com/SpecialReports/Article/38864http://www.devx.com/SpecialReports/Article/38884
  • 8/8/2019 5147 c++0 Special Report Op

    5/42

    Overview: C++ Gets an Overhaul

    Automatic type deduction is made possible by the new keywords auto and decltype which deduce

    the type of an object from its initializer and capture the type of an expression without having to

    spell it out, respectively. Adding auto and decltype also paves the way for a new function

    declaration syntax. The function's return type appears after the -> sign:

    auto func(int x)->double {return pow(x);}

    Lambda expressions and closures are another prominent feature of C++0x. A lambda expression

    is a nameless function defined at the place where it's called. It is similar to a function object except

    that the programmer is rid of the burden of declaring a class with a constructor, defining an

    overloaded () operator and an instantiating a temporary object of that classthis tedium nowbecomes the compiler's job. Here's an example of a lambda expression:

    //a lambda expression is used as an argument

    myfunc([](int x, int y) -> int {return x+y;} )

    The lambda expression is indicated by the lambda introducer [] followed by a parameter list in

    parentheses. The optional return type comes next, following the -> sign. Finally, the lambda block

    itself is enclosed in braces.

    Convenience Features

    Some C++0x features are meant to simplify recurring programming tasks and minimize boilerplate

    code. Most of these "convenience features" were borrowed from other programming languages.

    These convenience features include:

    A null pointer literal called nullptr

    Strongly-typed enumerations

    Delegating and inheriting constructors

    Listing 1 demonstrates these features.

    C++0x also removes some embarrassments from the language. For example, C++03 has at least

    three different forms of initialization:

    int x=0;

    int x(0);

    int y[2]={1,2};

    C++0x defines a unified initialization notation which can even be used in the declaration of

    dynamically allocated arrays:

    http://www.devx.com/cplus/10%20Minute%20Solution/37671/0http://www.devx.com/cplus/10%20Minute%20Solution/37854http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=254http://www.devx.com/cplus/10%20Minute%20Solution/35167/0http://www.devx.com/cplus/10%20Minute%20Solution/33504/0http://www.devx.com/cplus/10%20Minute%20Solution/33052/0http://www.devx.com/SpecialReports/Article/38884/1763?supportItem=1http://www.devx.com/SpecialReports/Article/38884/1763?supportItem=1http://www.devx.com/cplus/10%20Minute%20Solution/33052/0http://www.devx.com/cplus/10%20Minute%20Solution/33504/0http://www.devx.com/cplus/10%20Minute%20Solution/35167/0http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=254http://www.devx.com/cplus/10%20Minute%20Solution/37854http://www.devx.com/cplus/10%20Minute%20Solution/37671/0
  • 8/8/2019 5147 c++0 Special Report Op

    6/42

    Overview: C++ Gets an Overhaul

    int* a = new int[4] {1, 10, 20,95 };

    vector vs={"ab","cd","ef"};

    class S {

    int arr[3];

    public:

    S() : arr{ 1, 2, 3 } {}};

    More Control in Your Hands

    Certain new core features are meant to provide a standardized and uniform mechanism for

    controlling the compilation and execution environment programmatically. For example, take

    memory alignment. In C++03, you have to resort to compiler-dependent, non-portable hacks if you

    want to override the default alignment of your data. C++0x introduces two new operators: alignof

    and alignas that query and override the alignment requirements of your data, respectively:

    alignas (16) class Session

    {

    long long timestamp;

    int authorizations;

    bool active;

    //...

    };

    cout

  • 8/8/2019 5147 c++0 Special Report Op

    7/42

  • 8/8/2019 5147 c++0 Special Report Op

    8/42

    Overview: C++ Gets an Overhaul

    Perhaps the most popular Standard Library extension is the set of new smart pointer classes: std::

    tr1::shared_ptrand its little known sibling, std::tr1::weak_ptr.

    The class template std::tr1::array wraps a built-in array with a standard container's interface.

    Similarly, a tuple groups an arbitrary number of objects of unrelated types in single, container-like

    object. With respect to algorithms, 11 new algorithms were voted into draft standard in June 2008.Some of these algorithms fill holes in the C++98 standard, whereas others simplify common tasks.

    Here are some of them:

    all_of( first, last, pred): This returns true if all elements in the range satisfy the predicate

    pred

    any_of( first, last, pred): This returns true if any element in the range satisfies pred

    copy_n(first, n, result): This copies n elements into the result

    iota( first, last, value): For each element in the range, this assigns value and pre-increment

    value by ++value

    none_of( first, last, pred): This returns true if none of the elements in the range satisfiespred

    Finally, the range and subrange class templates of C++0x bundle pairs of iterators, thus

    significantly simplifying certain sequence operations and compacting the signatures of many

    popular algorithms.

    The Road Ahead

    The vast number of new features forces the committee to work at an incredible speed. A clear

    statement of intent was made to complete work on the new standard at the San Francisco meeting

    of September 2008 in order to achieve publication in 2009. To meet this ambitious timetable theplan is to vote out a feature complete Working Draft at the next meeting. A Final Committee Draft

    will be issued from the following meeting, allowing at least a minimal time for review and

    "integration testing" of the new featuresparticularly a conceptualized Standard Library.Danny Kalev is a certified system analyst and software engineer specializing in C++ and

    theoretical linguistics. He has an MA degree in general linguistics and is the author ofInformit C++

    Reference Guide and The ANSI/ISO Professional C++ Programmer's Handbook. Danny was a

    member of the C++ standards committee between 1997 and 2000. Danny recently finished his MA

    in general linguistics summa cum laude. In his spare time he likes to listen to classical music, read

    Victorian literature, and explore new natural and formal languages alike. He also gives lecturesabout programming and applied linguistics at academic institutes.

    DevX is a division of Jupitermedia Corporation

    Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices

    http://www.devx.com/cplus/10MinuteSolution/28347http://www.devx.com/cplus/10MinuteSolution/28347http://www.devx.com/cplus/10MinuteSolution/27219/0/page/2http://www.devx.com/cplus/10MinuteSolution/21712http://www.devx.com/cplus/10%20Minute%20Solution/36394/0http://www.informit.com/title/0536941467http://www.informit.com/title/0536941467http://www.amazon.com/exec/obidos/tg/detail/-/0789720221http://www.internet.com/corporate/legal.htmlhttp://www.internet.com/corporate/legal.htmlhttp://www.amazon.com/exec/obidos/tg/detail/-/0789720221http://www.informit.com/title/0536941467http://www.informit.com/title/0536941467http://www.devx.com/cplus/10%20Minute%20Solution/36394/0http://www.devx.com/cplus/10MinuteSolution/21712http://www.devx.com/cplus/10MinuteSolution/27219/0/page/2http://www.devx.com/cplus/10MinuteSolution/28347http://www.devx.com/cplus/10MinuteSolution/28347
  • 8/8/2019 5147 c++0 Special Report Op

    9/42

    Easier C++: An Introduction to Concepts

    C++0x:The Dawning of a New Standard

  • 8/8/2019 5147 c++0 Special Report Op

    10/42

    Easier C++: An Introduction to Concepts

    Originally from http://www.devx.com/SpecialReports/Article/38864

    Easier C++: An Introduction to ConceptsC++0x concepts bring the full power of the Generic Programming paradigm to C++,

    making templates more expressive, easier to write, and easier to use. Spectacularlypoor template error messages are a thing of the past!

    by Douglas Gregor

    very C++ programmer has had one of those days: A simple use of a template library turns intoa nightmare, with pages upon pages of error messages streaming out of the compiler. Somewhere

    in that proverbial haystack are the clues you will need to determine exactly what went wronganerror about a missing + operator here, an incompatible type assignment therebut you know youare in for a long search through the grisly internals of the template library, or a visit from your local

    C++ template guru.

    This article is not about C++ template error messages, but they are indicative of a far more

    general problem with the C++ template system. Most errors in the use of templates come from a

    misunderstanding between the author of the template and the user of the template. The author of

    the template expects the user's type to provide some specific set of operations, say, a + operator

    for addition and a copy assignment operator, which I'll refer to as the template requirements.

    When the user provides a type with the appropriate operations, i.e., the type satisfies the template

    requirements, everything works. However, when the user's type is missing some operations, the

    compiler reports the error as soon as the template tries to use that operation, which is often deep

    in the implementation of the template library. Thus, the template requirements are effectively a

    contract between the template author and user, and debugging a template error message is the

    act of trying to determine who broke the contractand how.Enter: Concepts

    Concepts is a language feature planned for C++0x that allows programmers to express the

    template requirements as part of the templates source code. Placing requirements on a template

    formalizes the contract between template author and user, allowing the compiler to ensure that

    both parties uphold their end of the bargain. The template author is permitted to use only

    operations that he has required the user to provide, while the template user is allowed to supply

    only types that provide all of the operations that the template requires. When both parties uphold

    C++Ox:The Dawning of a New Standard

    http://www.devx.com/SpecialReports/Article/38864http://www.devx.com/SpecialReports/Article/38864
  • 8/8/2019 5147 c++0 Special Report Op

    11/42

  • 8/8/2019 5147 c++0 Special Report Op

    12/42

    Easier C++: An Introduction to Concepts

    user and author so that the compiler can verify that both parties abide by the terms of the contract.

    Next, you'll see how the compiler verifies both sides of the contract.

    User's Side of the Contract

    To call the min() function, the user must provide a type for T that meets the LessThanComparable

    concept's requirements. Because C++ integers provide a less-than operator, the call min(17, 42) is

    a reasonable test. However, this call will fail with an error at the call site (not in the implementationof min()) stating that int is not LessThanComparable. The problem, in this case, is that the

    compiler does not know what the less-than operator in LessThanComparable actually means, and

    therefore cannot determine whether the built-in less-than provided for integers agrees with that

    meaning. Therefore, the user states explicitly that int meets the LessThanComparable concept's

    requirements through the use of a concept map:

    concept_map LessThanComparable { }

    Concept maps state that a particular type meets the concept's requirements. When one attempts

    to use a constrained template like min(17, 42), the compiler searches for a concept mapLessThanComparable and will find the concept map defined above, so the call succeeds.

    Concept maps play a second role in checking the user's side of the contract, because the concept

    maps themselves are verified against the body of the concept. In the concept map above, the

    compiler verifies that the int type has a suitable less-than operator (it happens to be a built-in

    operator), which returns a type that is convertible to bool. This checking can be seen when one

    attempts to write an incorrect concept map, for instance:

    concept_map LessThanComparable {

    } // error: no operator< for std::complex

    Because std::complex does not provide a less-than operator, the compiler will produce an

    error message stating that this type does not meet the LessThanComparable concept's

    requirements. Because you can't even define the concept map to state that complex numbers are

    LessThanComparable, you can't attempt to use the min() function. Most importantly, you never

    have to look into the actual body of min() to determine that there was an error; the requirements

    have all of the information you need.

    For trivial concepts such as LessThanComparable, the need to write a concept map for every type

    can become a bit onerous. For this reason, there is a special kind of concept, called an autoconcept, for which the compiler will automatically provide concept maps whenever they are

    needed. If you change the definition of the LessThanComparable concept to the following, users

    will no longer have to write concept maps for LessThanComparable to call the min() function:

    auto concept LessThanComparable {

    bool operator

  • 8/8/2019 5147 c++0 Special Report Op

    13/42

    Easier C++: An Introduction to Concepts

    Author's Side of the Contract

    When the author of a template places requirements on that template, the author is also bound by

    the terms of the contract. In particular, the author cannot use an object of type T with any

    operations not specified in the contract. With the min() function, for example, the body of the

    function can use only the < operator on objects of type T, because only the < operator is specified

    by the LessThanComparable concept. Suppose you tried to implement a max() function with

    LessThanComparable as follows:

    template

    requires LessThanComparable

    const T& max(const T& x, const T& y) {return x > y? x : y; // error: no operator>(T, T)

    }

    In this example, the author specified in the contract that the type T would provide a ''. The compiler will produce an error message when it processes the

    template stating that no such '>' operator exists. Therefore, the template author is bound by the

    same contract as the user, and there cannot be any surprises where the template author states

    one requirement in the contract but uses a slightly different operation in the implementation. This

    is exactly the kind of problem that occurs with template libraries today: Because most types that

    max() would be tested with will have both less-than and greater-than operations, the latent

    errorthat the function requires less-than but uses greater-thanis unlikely to be detected by testing.With concepts, however, the compiler detects this form of error immediately.

    Because both the template author and user are held to the same contract, the compiler canprovide an extremely important guarantee: If both the template's implementation and the use of

    the template meet the contract's requirements, the instantiation of that template will not fail. There

    are two practical effects to this guarantee. First, concepts eliminate the spectacularly poor error

    messages produced by long instantiation backtraces, because the failures occur before template

    instantiation is even attempted. Second, both users and library authors can have a far greater

    level of confidence in template libraries using concepts than in the corresponding pre-concept

    libraries, because the compiler takes a more active role in verifying the correctness of templates.

    The Perimeter of a Polygon

    Listing 2 contains a simple algorithm that computes the perimeter of the polygon it is given, by

    summing the lengths of each of the sides of the polygon. Polygons are described by the Polygon

    concept, which provides functions that determine the number of sides and the length of a given

    side.

    The Polygon concept's requirements can be satisfied by many different data types. For example,

    you can implement a simple triangle class that can be passed to the perimeter() function:

    class triangle {

    http://www.devx.com/SpecialReports/Article/38864/1763?supportItem=2http://www.devx.com/SpecialReports/Article/38864/1763?supportItem=2
  • 8/8/2019 5147 c++0 Special Report Op

    14/42

    Easier C++: An Introduction to Concepts

    public:int sides[3];

    };

    int num_sides(const triangle& tri) { return 3; }int side_length(const triangle& tri, int index) {

    return tri.sides[index];}

    concept_map Polygon { }

    The triangle class provides the operations required by the Polygon concept, num_sides() and

    side_length(). Note, however, that while the Polygon concept expects side_length() to return a

    double, triangle's version of side_length() returns an int. This is not an error. Concept maps

    provide one level of conversions, which will automatically convert the int returned by triangle's

    num_sides() into the double expected by users of the Polygon concept. This way, minor

    mismatches in the interface between the template user and the template author are resolvedautomatically in the concept map, making constrained templates more widely applicable.

    Associated Types

    The implementation of perimeter() works with the triangle class, but it is suboptimal; despite the

    fact that the sides of the triangle are specified in terms of integers, all of the computation in

    perimeter() is performed via floating-point arithmetic. To solve this problem, the algorithm should

    instead perform the computation using the same type that the polygon uses to express the lengths

    of its sides, which may vary from one type to another.

    Concepts provide a way to express such types, which vary from one use of a concept to another:

    associated types. Associated types are declared within the body of a concept via the typename

    keyword (using the same syntax as template type parameters), and can be used to describe

    operations within the concept. You can now revise the Polygon concept to introduce an associated

    type named length_type, which is used to express the length of a single side in the polygon, and

    therefore is the return type of the side_length() operation:

    concept Polygon {

    typename length_typeint num_sides(const P&);length_type side_length(const P&, int index);

    }

    Because the types of concept operations are important wherever the concepts are used, you can

    refer to an associated type as a nested type within the concept. For example, an updated

    perimeter() algorithm should refer to the length_type of the Polygon concept explicitly, rather than

    using double:

  • 8/8/2019 5147 c++0 Special Report Op

    15/42

    Easier C++: An Introduction to Concepts

    templaterequires Polygon

    Polygon

    ::length_type perimeter(const P& poly) {

    Polygon

    ::length_type sum = 0; // error!

    for (int i = 0; i < num_sides(poly); ++i)

    sum += side_length(poly, i); // error!return sum; // error!

    }

    Here, the uses of double are replaced with Polygon

    ::length_type, which has made the

    algorithm capable of handling different length types, and therefore more reusable. However, this

    change has introduced some new errors that will be detected by the compiler. Previously, the

    algorithm was relying on the built-in operations provided by double: construction from an integer,

    addition via +=, and copy-construction of the return value. With an arbitrary length_type, you can

    no longer assume that all of these operations are available. They have to be specified as

    requirements on the length type, which the user's length type must satisfy.

    Member-Function Requirements

    To express the length type's requirements, we introduce another new concept, Numeric. The

    Numeric concept provides the essential operations required to sum a value:

    auto concept Numeric {

    T::T(const T&); // copy constructionT::T(int); // construction from an int

    T::~T(); // destructor

    T& operator+=(T&, const T&); // addition}

    The first three operations in the Numeric concept require a copy constructor (which can be

    satisfied by a built-in initialization), the ability to construct a value of type T from an int, and the

    ability to destroy an object of type T. Each of these operations is stated using member function

    syntax with the T:: prefix, specifying that these operations apply to objects of type T. The same

    syntax can be used to describe specific member functions requirements (for example, T::clone()).

    Armed with the Numeric concept, you can express the perimeter() algorithm's full requirements as:

    template

    requires Polygon

    && NumericPolygon

    ::length_type perimeter(const P& poly);

    The "&&" in the requires clause states that both requirements must be satisfied for the algorithm to

    be usable, that is, the type P must be a Polygon and its length_type must be Numeric. Any

    number of different requirements can be added to a template using "&&", including multiple

  • 8/8/2019 5147 c++0 Special Report Op

    16/42

    Easier C++: An Introduction to Concepts

    requirements on the same types.

    Associated Requirements

    Adding the Numeric requirement to the perimeter() concept is correct, but it is not ideal. The

    requirement that the length_type of a Polygon be Numeric isn't solely a property of perimeter(): It'sa more universal property that polygons only make sense if their length types are proper numeric

    types. To support this common usage, concepts support associated requirements, which specify

    extra requirements on the associated types of a concept within the concept body. Here is the final

    version of the Polygon concept, which makes use of associated requirements:

    concept Polygon {typename length_type;

    requires Numeric;

    int num_sides(const P&);

    length_type side_length(const P&, int index);}

    With this change, you can remove the explicit Numeric requirement from the perimeter() algorithm,

    because the length type of a Polygon is always numeric. For the final declaration of this perimeter

    () algorithm, I've also employed two syntactic shortcuts, which simplify the expression of template

    requirements and simplify access to associated types:

    template

    P::length_type perimeter(const P& poly);

    The first shortcut is the use of Polygon P, which states that P is a template type parameter whose

    requirement is Polygon

    ; it is identical to writing the same requirement within a requires clause.

    The second shortcut is the use of P::length_type, which searches for an associated type named

    length_type within the requirements placed on P, and is identical to Polygon

    ::length_type.

    Syntax Remapping with Concept Maps

    All the concept maps so far have had empty bodies within their curly braces, and have been used

    to state (and check) that a type meets the concept requirements. However, concept maps need

    not be empty: they can contain definitions that specify how a type meets the conceptrequirements, and can even contain new functions that allow one to map the syntax provided by a

    type to the syntax expected by the concept. For example, start with a simple rectangle structure:

    struct rectangle {

    double left, top, right, bottom;};

  • 8/8/2019 5147 c++0 Special Report Op

    17/42

    Easier C++: An Introduction to Concepts

    You could add appropriate num_sides() and side_length() functions to this type to make it look like

    a Polygon. But, this expands the interface in a way that might not be desirable if the only purpose

    is to use the perimeter() function. Instead, you can write a concept map that makes the rectangle

    look like a polygon:

    concept_map Polygon {

    typedef double length_type;

    int num_sides(const rectangle&) { return 4; }

    double side_length(const rectangle& rect, int index) {return index % 2? fabs(rect.right rect.left)

    : fabs(rect.bottom rect.top);

    }

    }

    In this concept map, the Polygon concept's requirements are satisfied by the body of the concept

    map itself. The functions provided by the concept map are visible only through the concept itself,

    and are not part of the public interface of the rectangle structure (which has not changed). Only

    those constrained templates that operate on Polygons will see this particular view of the rectangle

    structure.

    Through this syntax-remapping mechanism, an existing type can be adapted to meet an existing

    concept's requirements without changing either the type or the concept, allowing far greater reuse

    of generic algorithms than is possible without concept maps.

    Concept Refinement and Concept-Based Overloading

    It is often the case when implementing a generic algorithm that there are several possible

    implementations, each of which involves different trade-offs. Some implementations may apply to

    a wide variety of data types (are very generic) while others operate more efficiently on a more

    narrow range of data types (are more specialized). For example, the generic perimeter() algorithm

    operates on any polygon in linear time, but there is a more efficient implementation: If you know

    that the polygon is an equilateral polygon (where all sides have the same length), you could

    compute the perimeter with a single multiplication. Like Polygon, EquilateralPolygon is a concept

    that describes types that behave like polygons.

    You could implement an EquilateralPolygon separately from the Polygon concept, but doing so

    misses an important opportunity for reuse, because every equilateral polygon is also a polygon.

    You can therefore express EquilateralPolygon as a refinementof the Polygon concept:

    concept EquilateralPolygon : Polygon

    { }

  • 8/8/2019 5147 c++0 Special Report Op

    18/42

    Easier C++: An Introduction to Concepts

    As the syntax implies, concept refinement is similar to concept "inheritance," because the refining

    concept (EquilateralPolygon) inherits all of the base concept's requirements (Polygon).

    Additionally, a type that is an EquilateralPolygon can be used in any algorithm that expects a

    Polygon, meaning that this square class could be used with the existing perimeter() algorithm:

    class square {

    public:int length;

    };

    concept_map EquilateralPolygon {typedef int length_type;

    int num_sides(const square&) { return 4; }

    int side_length(const square& sq, int) {

    return sq.length;}

    }

    Concept refinement describes a hierarchical "is-a" relationship that can also be used by concept-

    based overloading, which involves overloading constrained templates on their requirements. As

    noted before, you can write a constant-time algorithm for computing the perimeter of an equilateral

    polygon, assuming you've already added a suitable multiplication operator to the Numeric concept:

    templateP::length_type perimeter(const P& poly) {

    return num_sides(poly) * side_length(poly, 0);}

    This implementation of perimeter() overloads the previous, Polygon-based implementation. For

    types that are non-equilateral Polygons, the previous (linear-time) implementation will be used,

    because this (constant-time) constrained template's requirements will not be satisfied. For

    equilateral polygons like square, both implementations are valid because every equilateral

    polygon is a polygon. In this case, concept-based overloading picks the overload corresponding to

    the more refined concept, automatically selecting the constant-time implementation of perimeter().Concept-based overloading (and, related, concept-based partial specialization of class templates)

    allows the user to provide multiple, different variations of the same algorithm, which differ only by

    the properties of the types that they support, and the compiler will select the most appropriate

    algorithm variation for each call site.

    Truly Easier C++

    Concepts are a significant extension to the C++ template system. By allowing template authors to

    explicitly describe the template requirements, the compiler is able to verify both the template

    authors and the template user's side of the (previously implicit) template contract. This additional

  • 8/8/2019 5147 c++0 Special Report Op

    19/42

    Easier C++: An Introduction to Concepts

    type checking makes it easier to write templates (because they cannot violate the stated contract)

    and use templates (because contract violations result in far more readable error messages). The

    use of template requirements also enables advanced features that make templates more

    reusable, such as the ability to remap syntax within concept maps, and more expressive, through

    the use of concept-based overloading.

    As of this writing, concepts are expected to be included in the C++0x language and standardlibrary. However, concepts have not yet been voted into the working paper by the ISO C++

    standards committee, and some small details may still change. Watch for more interesting

    developments in C++0x and the concepts mechanism.

    Douglas Gregoris an active member of the ISO C++ committee, where he has lead the

    development and specification of various C++09 features, including concepts and variadic

    templates. A long-time contributor to Boost, Doug has developed several Boost libraries and acts

    as a moderator for the Boost community. Doug is currently the assistant director of the Open

    Systems Lab at Indiana University, where his research involves generic programming, parallel

    programming, and large-scale graph analysis.

    DevX is a division of Jupitermedia Corporation

    Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices

    http://www.internet.com/corporate/legal.htmlhttp://www.internet.com/corporate/legal.html
  • 8/8/2019 5147 c++0 Special Report Op

    20/42

    Simpler Multithreading in C++0x

    C++0x:The Dawning of a New Standard

  • 8/8/2019 5147 c++0 Special Report Op

    21/42

    Simpler Multithreading in C++0x

    Originally from http://www.devx.com/SpecialReports/Article/38883

    Simpler Multithreading in C++0xThe new standard will support multithreading, with a new thread library. Find out how thiswill improve porting code, and reduce the number of APIs and syntaxes you use.

    by Anthony Williams

    ne major new feature in the C++0x standard is multi-threading support. Prior to C++0x, any multi-

    threading support in your C++ compiler has been provided as an extension to the C++ standard, which

    has meant that the details of that support varies between compilers and platforms. However, with the

    new standard, all compilers will have to conform to the same memory model and provide the same

    facilities for multi-threading (though implementors are still free to provide additional extensions). What

    does this mean for you? It means you'll be able to port multi-threaded code between compilers and

    platforms with much reduced cost. This will also reduce the number of different APIs and syntaxes youll

    have to know when writing for multiple platforms.

    The core of the new thread library is the std::thread class, which manages a thread of execution, so let'sstart by looking at that.

    Launching Threads

    You start a new thread by constructing an instance of std::thread with a function. This function is then

    used as the entry point for the new thread, and once that function returns, the thread is finished:

    void do_work();

    std::thread t(do_work);

    This is just like the thread-creation APIs we're all used tobut there's a crucial difference: This is C++, sowe're not restricted to functions. Just like many of the algorithms in the Standard C++ Library, std::threadwill accept an object of a type that implements the function call operator (operator()), as well as ordinary

    functions:

    class do_work

    {

    public:

    void operator()();

    };

    C++Ox:The Dawning of a New Standard

    http://www.devx.com/SpecialReports/Article/38883http://www.devx.com/SpecialReports/Article/38883
  • 8/8/2019 5147 c++0 Special Report Op

    22/42

    Simpler Multithreading in C++0x

    do_work dw;

    std::thread t(dw);

    It's important to note that this actually copies the supplied object into the thread. If you really want to use

    the object you supplied (in which case, you'd better make sure that it doesn't get destroyed before the

    thread finishes), you can do so by wrapping it in std::ref:

    do_work dw;

    std::thread t(std::ref(dw));

    Most thread creation APIs allow you to pass a single parameter to your newly created thread, typically a

    long or a void*. std::thread allows arguments too, but you can pass any number, of (almost) any type.

    Yes, you read that right: any number of arguments. The constructor uses C++0x's new variadic template

    facility to allow a variable number of arguments like the old ... varargs syntax, but in a type-safe manner.

    You can now pass objects of any copyable type as arguments to the thread function:

    void do_more_work(int i,std::string s,std::vector v);

    std::thread

    t(do_more_work,42,"hello",std::vector(23,3.141));

    Just as with the function object itself, the arguments are copied into the thread before the function is

    invoked, so if you want to pass a reference you need to wrap the argument in std::ref:

    void foo(std::string&);

    std::string s;std::thread t(foo,std::ref(s));

    OK, that's enough about launching threads. What about waiting for the thread to finish? The C++

    Standard calls that "joining" with the thread (after the POSIX terminology), and you do that with the join()

    member function:

    void do_work();

    std::thread t(do_work);

    t.join();

    If you're not planning on joining with your thread, just destroy the thread object or call detach():

    void do_work();

    std::thread t(do_work);

    t.detach();

    Now, it's very well launching all these threads, but if you're going to share data you'd better protect it. The

    new C++ Standard Library provides facilities for that, too.

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf
  • 8/8/2019 5147 c++0 Special Report Op

    23/42

    Simpler Multithreading in C++0x

    Protecting Data

    In the C++0x thread library, as with most thread APIs, the basic facility for protecting shared data is the

    mutex. In C++0x, there are four varieties of mutexes:

    non-recursive (std::mutex) recursive (std::recursive_mutex)

    non-recursive that allows timeouts on the lock functions (std::timed_mutex)

    recursive mutex that allows timeouts on the lock functions (std::recursive_timed_mutex)

    All of them provide exclusive ownership for one thread. If you try and lock a non-recursive mutex twice

    from the same thread without unlocking in between, you get undefined behavior. A recursive mutex

    simply increases the lock countyou must unlock the mutex the same number of times that you locked itinorder for other threads to be allowed to lock the mutex.

    Though these mutex types all have member functions for locking and unlocking, in most scenarios the

    best way to do it is with the lock class templates std::unique_lock and std::lock_guard. Theseclasses lock the mutex in the constructor and release it in the destructor. Thus, if you use them as local

    variables, your mutex is automatically unlocked when you exit the scope:

    std::mutex m;

    my_class data;

    void foo()

    {

    std::lock_guard lk(m);

    process(data);} // mutex unlocked here

    std::lock_guard is deliberately basic and can only be used as shown. On the other hand, std::unique_lock

    allows for deferred locking, trying to lock, trying to lock with a timeout, and unlocking before the object is

    destroyed. If you've chosen to use std::timed_mutex because you want the timeout on the locks, you

    probably need to use std::unique_lock:

    std::timed_mutex m;

    my_class data;

    void foo()

    {

    std::unique_lock

    lk(m,std::chrono::milliseconds(3)); // wait up to 3ms

    if(lk) // if we got the lock, access the data

    process(data);

    } // mutex unlocked here

    These lock classes are templates, so they can be used with all the standard mutex types, plus any

  • 8/8/2019 5147 c++0 Special Report Op

    24/42

    Simpler Multithreading in C++0x

    additional types that supply lock() and unlock() functions.

    Protecting Against Deadlock When Locking Multiple Mutexes

    Occasionally, an operation requires you to lock more than one mutex. Done wrong, this is a nasty source

    of deadlocks: Two threads can try and lock the same mutexes in the opposite order, with each end

    upholding one mutex and waiting for the other thread to finish with the other mutexes. The C++0x thread

    library allievates this problem, in those cases where you wish to acquire the locks together, by providing

    a generic std::lock function that can lock multiple mutexes at once. Rather than calling the lock() member

    function on each mutex in turn, you pass them to std::lock(), which locks them all without risking

    deadlock. You can even pass in currently unlocked instances of std::unique_lock:

    struct X

    {

    std::mutex m;

    int a;

    std::string b;

    };

    void foo(X& a,X& b)

    {

    std::unique_lock lock_a(a.m,std::defer_lock);

    std::unique_lock lock_b(b.m,std::defer_lock);

    std::lock(lock_a,lock_b);

    // do something with the internals of a and b

    }

    In the above example, suppose you didn't use std::lock. This could possibly result in a deadlock if onethread did foo(x,y) and another did foo(y,x) for two X objects x and y. With std::lock, this is safe.

    Protecting Data During Initialization

    If your data only needs protecting during its initialization, using a mutex is not the answer. Doing so only

    leads to unnecessary synchronization after initialization is complete. The C++0x standard provides

    several ways of dealing with this.

    First, suppose your constructor is declared with the new constexpr keyword and satisfies the

    requirements for constant initialization. In this case, an object of static storage duration, initialized with

    that constructor, is guaranteed to be initialized before any code is run as part of the static initialization

    phase. This is the option chosen for std::mutex, because it eliminates the possibility of race conditions

    with initialization of mutexes at a global scope:

    class my_class

    {

    int i;

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf
  • 8/8/2019 5147 c++0 Special Report Op

    25/42

    Simpler Multithreading in C++0x

    public:

    constexpr my_class():i(0){}

    my_class(int i_):i(i_){}

    void do_stuff();

    };

    my_class x; // static initialization with constexpr constructor

    int foo();

    my_class y(42+foo()); // dynamic initialization

    void f()

    {

    y.do_stuff(); // is y initialized?

    }

    Your second option is to use a static variable at block scope. In C++0x, initialization of block scope static

    variables happens the first time the function is called. If a second thread should call the function before

    the initialization is complete, then that second thread has to wait:

    void bar()

    {

    static my_class z(42+foo()); // initialization is thread-safe

    z.do_stuff();

    }

    If neither options apply (perhaps because the object is dynamically allocated), then it's best to use std::

    call_once and std::once_flag. As the name suggests, when std::call_once is used in conjunction with a

    specific instance of type std::once_flag, the specified function is called exactly once:

    my_class* p=0;

    std::once_flag p_flag;

    void create_instance()

    {p=new my_class(42+foo());

    }

    void baz()

    {

    std::call_once(p_flag,create_instance);

    p->do_stuff();

    }

  • 8/8/2019 5147 c++0 Special Report Op

    26/42

    Simpler Multithreading in C++0x

    Just as with the std::thread constructor, std::call_once can take function objects instead of functions, and

    can pass arguments to the function. Again, copying is the default, and you have to use std::ref if you want

    a reference.

    Waiting for EventsIf you're sharing data between threads, you often need one thread to wait for another to perform some

    action, and you want to do this without consuming any CPU time. If a thread is simply waiting for its turn

    to access some shared data, then a mutex lock can be sufficient. However, generally doing so won't

    have the desired semantics.

    The simplest way to wait is to put the thread to sleep for a short period of time. Then check to see if the

    desired action has occurred when the thread wakes up. It's important to ensure that the mutex you use to

    protect the data indicating that the event has occurred is unlocked whilst the thread is sleeping:

    std::mutex m;

    bool data_ready;

    void process_data();

    void foo()

    {

    std::unique_lock lk(m);

    while(!data_ready)

    {

    lk.unlock();

    std::this_thread::sleep_for(std::chrono::milliseconds(10));lk.lock();

    }

    process_data();

    }

    This method may be simplest, but it's less than ideal for two reasons. Firstly, on average, the thread will

    wait five ms (half of ten ms) after the data is ready before it will wake in order to check. This may cause a

    noticeable lag in some cases. Though this can be improved by reducing the wait time, it exacerbates the

    second problem: the thread has to wake up, acquire the mutex, and check the flag every ten mseven ifnothing has happened. This consumes CPU time and increases contention on the mutex, and thuspotentially slows down the thread performing the task for which it's waiting!

    If you find yourself writing code like that, don't: Use condition variables instead. Rather than sleeping for

    a fixed period, you can let the thread sleep until it has been notified by another thread. This ensures that

    the latency between being notified and the thread waking is as small as the OS will allow, and effectively

    reduces the CPU consumption of the waiting thread to zero for the entire time. You can rewrite foo to use

    a condition variable like this:

    std::mutex m;

  • 8/8/2019 5147 c++0 Special Report Op

    27/42

    Simpler Multithreading in C++0x

    std::condition_variable cond;

    bool data_ready;

    void process_data();

    void foo()

    {

    std::unique_lock lk(m);

    while(!data_ready)

    {

    cond.wait(lk);

    }

    process_data();

    }

    Note that the above code passes in the lock object lk as a parameter to wait(). The condition variable

    implementation then unlocks the mutex on entry to wait(), and locks it again on exit. This ensures that the

    protected data can be modified by other threads whilst this thread is waiting. The code that sets the

    data_ready flag then looks like this:

    void set_data_ready()

    {

    std::lock_guard lk(m);

    data_ready=true;cond.notify_one();

    }

    You still need to check that the data is ready though, since condition variables can suffer from what are

    called spurious wakes: The call to wait() may return even though it wasn't notified by another thread. If

    you're worried about getting this wrong, you can pass that responsibility off to the standard library too, if

    you tell it what you're waiting for with a predicate. The new C++0x lambda facility makes this really easy:

    void foo()

    {std::unique_lock lk(m);

    cond.wait(lk,[]{return data_ready;});

    process_data();

    }

    What if you don't want to share your data? What if you want exactly the opposite: For each thread to

    have its own copy? This is the scenario addressed by the new thread_local storage duration keyword.

  • 8/8/2019 5147 c++0 Special Report Op

    28/42

    Simpler Multithreading in C++0x

    Thread Local Data

    The thread_local keyword can be used with any object declaration at namespace scope at local scope,

    and specifies that such a variable is thread local. Each thread thus has its own copy of that variable, and

    that copy exists for the entire duration of that thread. It is essentially a per-thread static variable, so each

    thread's copy of a variable declared at local scope is initialized the first time that particular thread passes

    through the declaration, and they retain their values until that thread exits:

    std::string foo(std::string const& s2)

    {

    thread_local std::string s="hello";

    s+=s2;

    return s;

    }

    In this function, each thread's copy of s starts life with the contents "hello." Every time the function iscalled, the supplied string is appended to that thread's copy of s. As you can see from this example, this

    even works with class types that have constructors and destructors (such as std::string), which is an

    improvement over the pre-C++0x compiler extensions.

    Thread-local storage isn't the only change to the concurrency support in the core language: There's also

    a brand new multi-threading aware memory model, with support for atomic operations.

    The New Memory Model and Atomic Operations

    Sticking to using locks and condition variables to protect your data, you won't need to worry about the

    memory model. The memory model guarantees to protect your data from race conditionsif you use lockscorrectly. You'll get undefined behavior if you don't.

    If you're working at a really low-level and providing high-performance library facilities, then it's important

    to know the detailswhich are too complicated to go into here. For now, it's enough to know that C++0xhas a set of atomic types corresponding to the built-in integer types and void pointersand a template std::atomicwhich can be used to create an atomic version of a simple user-defined type. You can look upthe relevant documentation for the details.

    That's All, Folks!

    And thats your whistle-stop tour of the new C++0x threading facilities, which has barely scratched the

    surface. There's much more to the library, with features such as thread IDs and asynchronous future

    values.

    Anthony Williams is the Technical Director forJust Software Solutions Ltd., where he spends most of

    his time developing custom software for clients, mostly for Windows, and mostly C++. He is the

    maintainer of the Boost Thread library and is also a member of the BSI C++ Standards Panel. His latest

    book, 'C++ Concurrency in Action: Practical Multithreading' is currently available in the Early Access

    Edition from Manning's web site.

    DevX is a division of Jupitermedia Corporation

    Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices

    http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2007/n2427.htmlhttp://www.justsoftwaresolutions.co.uk/http://www.boost.org/http://www.manning.com/williams/http://www.boost.org/http://www.justsoftwaresolutions.co.uk/http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2007/n2427.html
  • 8/8/2019 5147 c++0 Special Report Op

    29/42

    The State of the Language:

    An Interview with Bjarne Stroustrup

    C++0x:The Dawning of a New Standard

  • 8/8/2019 5147 c++0 Special Report Op

    30/42

    The State of the Language: An Interview with Bjarne Stroustrup

    Originally from http://www.devx.com/SpecialReports/Article/38813

    The State of the Language: An Interview with Bjarne StroustrupC++ founding father assesses the language on the eve of its new standard.

    by Danny Kalev

    Bjarne Stroustrup, inventor of the C++ programming language, is a computer scientist and the College of Engineering Chair

    Professor of Computer Science at Texas A&M University. He has always been highly involved in the standardization of C++.

    Since 2004, Bjarne and the standards committee have been busy hammering out the details of a new standard, temporarily

    titled C++0x. Bjarne was gracious enough to take time out of his busy schedule to speak with DevX C++ Pro, Danny Kalev,about new C++0x features and the state of the C++ language.

    The C++0x standard will be finalized during 2009. Can you outline its major features and its overall importance

    to the C++ community?

    We hope to vote out a draft standard for public review in October 2008 so that we'll be able to hand in a final draft for

    international vote in 2009. Because of this heavy ISO process, it's touch and go whether C++0x will be C++09, but there is

    still hope and the major features are now known (barring disasters). We can classify the extensions like this

    Concurrency:

    memory model supporting modern machine architectures

    Threading ABI

    atomic types

    mutexes and locks

    thread local storage

    asynchronous message exchange

    Libraries:

    regex: regular expressions

    unordered_map, etc. (hash tables)

    smart pointers

    array: fixed-sized array

    improvements to containers based on new C++0x features

    tuples

    date and time (maybe)

    various library components to held library builders

    Language:

    rvalue references (move semantics)

    static_assert: static assertions

    C++Ox:The Dawning of a New Standard

    http://www.devx.com/SpecialReports/Article/38813http://www.devx.com/cplus/10%20Minute%20Solution/37436/0http://www.devx.com/cplus/10%20Minute%20Solution/28347/0http://www.devx.com/cplus/10MinuteSolution/21712http://www.devx.com/cplus/10MinuteSolution/21712http://www.devx.com/cplus/10%20Minute%20Solution/28347/0http://www.devx.com/cplus/10%20Minute%20Solution/37436/0http://www.devx.com/SpecialReports/Article/38813
  • 8/8/2019 5147 c++0 Special Report Op

    31/42

    The State of the Language: An Interview with Bjarne Stroustrup

    variadic templates

    strongly typed enumerations with scoped enumerators

    constexpr: generalized constant expressions

    control of alignment

    delegating and inheriting constructors

    auto: deducing a type from an initializer

    decltype: a way of using the type of an expression in a declaration

    control of defaults

    nullptr: a name for the null pointer

    a range-based for loop

    lambda functions

    raw string literals

    UTF8 literals

    concepts (a type system for template arguments)

    initializer lists and uniform initializations syntax and semantics

    in-class member initializers

    Lists are, by themselves, not very interesting, but you can read up on a description of my general philosophy for language

    evolution and some of the individual decisions in my HOPL-iii paper "Evolving a language in and for the real world: C++

    1991-2006." You can also find more information than you could possibly want on the committee's web site.

    Basically, the "concurrency" features will standardize the basic layers needed to do systems programming in a multi-core

    world. Obviously, facilities for doing that already exist in C++ implementations, but they are not standardized. I'd have liked

    to see library support for some high-level concurrency models, but the committee didn't have the time or consensus for that.

    "I'd have liked to see

    library support for some

    high-level concurrency

    models, but the

    committee didn't have

    the time or consensus

    for that."

    The library facilities provide a set of new library components and some improvements to

    the existing ones. I would have liked to see many more, but the committee is a volunteer

    effort and we just didn't have the resources for a massive extension of what was offered.

    Fortunately, there are many libraries available "out there," possibly already on your

    machine. For example, many of the C++0x libraries (e.g., regex and unordered_map) are

    now shipped by major vendors and boost.org offers many components (for instance, file

    system and networking) that we'll probably soon see in the standard. There is also much

    talk of a technical report on the libraries we most wanted but had to postpone.

    The language extensions are a varied lot. Fortunately most are small and fit together with each other and with existing

    facilities to make a better integrated language. Consider a few examples:

    // using C++0x features:

    vector v = {"Gorm", "Harald", "Sven", "Harald", "Knud" };

    for (auto p = v.begin(); p!=v.end(); ++p) cout

  • 8/8/2019 5147 c++0 Special Report Op

    32/42

    The State of the Language: An Interview with Bjarne Stroustrup

    making errors and/or for introducing overhead.

    Note that all "primitive" features are meant to be used in combination and in combination with existing features to solve

    problems. For example, there is no "magic" for initializing vectors in particular or even any new "magic" for constructors.

    Instead, the initialization of vector was achieved simply by a rule that state that an initializer_list can be initialized by a list

    of any numbers of Ts {t1, t2, t3} for any type T. Given that rule, we simply give vector a constructor that accepts an

    initializer_list. Incidentally, this mechanism can also be used to eliminate about 80 percent of the uses of the type-unsafe

    stdargs macros.

    Concepts are probably the most important addition to C++ in years. Can you please explain which problems in

    contemporary C++ concepts will solve?

    I suspect that what is most important depends on what you consider important. For many, concepts will be invisible.

    They will simply be "the magic" behind a radical improvement of the error messages you get when you make a mistake

    using something that happens to be a template. Basically, you'll get the kind of error messages that you are used to from

    "ordinary functions" and at the time you get them for mistakes with ordinary functions. What's so great about that? I can

    imagine a time a few years into the future where people won't be able to think of a good answer to that question. This will be

    the ultimate proof of the success of concepts.

    "Concepts" is a type system for types, combinations of types, and combinations of types and integers. Basically, it allows the

    programmer to state in code what we currently state in documentation and comments. For example, the standard algorithm

    takes a pair of forward iterators and a value; given that, it assigns the value to each element of the sequence defined by the

    iterators. That algorithm's requirements on its argument types can be expressed like this:

    template

    requires Assignable

    void fill(For first, For last, const V& v); // just a declaration, not definition

    We can try using fill():

    int i = 0;

    int j = 9;

    fill(i, j, 99); // error: int is not a Forward_iterator

    int* p= &v[0];

    int* q = &v[9];

    fill(p, q, 99); // ok: int* is a Forward_iterator

    The checking of use happens immediately at the call site and uses only the declaration. This is a major practical advantage

    over the current state of affairs for templates where the checking happens lateduring template instantiation time.Concepts also allow us to check the definition of a template in isolations from its arguments:

    template

    requires Assignable

    void fill(For first, For last, const V& v)

    {

    while (first!=last) {

    *first = v;

    first=first+1; // error: + not defined for Forward_iterator

    // (instead: use ++first)

  • 8/8/2019 5147 c++0 Special Report Op

    33/42

    The State of the Language: An Interview with Bjarne Stroustrup

    }

    }

    Again, the error is immediately caught at the point in the definition where it happens.

    This checking is the most obvious benefit of concepts, but they also give greatly improved specification of algorithms and

    class templates and makes overloading straightforward, eliminating the complicated scaffolding of traits and helper functions

    that people have to rely on today.

    Most importantly, concepts help us think about our algorithms and their requirements on their (template) arguments. This

    leads to more reliable and more general code. Often, such thinking also leads to improved performance as we are forced to

    think about what the algorithm really needs and what is extraneous.

    Let's talk about rvalue references. Will they also be "mostly invisible" as concepts, allowing library writers to

    implement perfect forwarding and move semantics or will they affect the average C++ programmer's code more

    visibly? For instance, will C++ have a fifth canonical member function called a move constructor?

    Yes, rvalue references are very much a "technical extension" meant to be invisible to 99.9 percent of programmers.

    Their main effect will be some speedup in the implementation of common containers (e.g. vector) and algorithms.

    The basic idea behind rvalue references is that we often copy a value when all we wanted was to move it; that is, after a=b,

    we have two copies of the value of b, but often the very next thing we do is to destroy b. With rvalue references, we can write

    a function move() so that we can write a=move(b) to express that idea. If b is something large (e.g. a string or a matrix), the

    performance advantage can be significant (i.e. a factors rather than a small percent). Such move operations will be sprinkled

    around in the standard library implementation so that you gain the performance advantage even if you have never heard of

    rvalue references.

    For example, some standard library classes (e.g. string and vector) will have "move constructor":

    T::T(T&&);

    which can basically be read as "T doesn't waste time making copies where it can move."

    In your recent SD West lecture, you predicted that "concepts are going to be sexy for awhile, then overused

    and then people will get sick of it. When things calm down, we'll find out when and where they're actually useful."

    Where do you draw the line between valid, welcome usage of concepts as opposed to "overuse"? In other words,

    what shouldn't we do with concepts?

    I'm pretty sure that was a comment about generic programming in general, rather than about concepts in particular. I'm

    hesitant to draw a sharp line. Doing so would imply that I thought I knew what would be right (and not) for essentially all

    people in essentially all application areas. I don't, and drawing such lines is also a sign of paternalistic language design. You

    can "draw lines" for individuals and organizations (that's what coding standards are for), but not for a set of general language

    features for a general-purpose language. The point about "general" is that programmers will discover techniques beyond the

    use cases that the language designers thought of. When a new and powerful feature becomes available, it gets overused as

    adventurous programmers try to push it to the limit. In the early days of C++, we got inline virtual overloaded functions in

    multiply inherited classes. When templates were new, we got excessively clever template meta-programming. This will

    happen again with the C++0x feature set. I just hope that this time more people can tell the difference between an

    experiment and something ready to put into production code.

    Actually, many of the C++0x features, including concepts, are there to ensure that less

  • 8/8/2019 5147 c++0 Special Report Op

    34/42

    The State of the Language: An Interview with Bjarne Stroustrup

    "Actually, many of the C+

    +0x features, including

    concepts, are there to

    ensure that less

    cleverness is needed to

    express interesting

    things and to make what

    is expressed better

    checked."

    cleverness is needed to express interesting things and to make what is expressed better

    checked. Naturally, that will free up time and energy for even more extreme/interesting

    experiments.

    What shouldn't we do with concepts? I don't know, but first, I'd use them to precisely and

    exhaustively express the requirements of generic algorithms on their (template)

    arguments. That should keep me busy for a while. For starters, there is all of the Standard

    Library (being done by the committee and in particular by Doug Gregorand friends) and

    all of classical mathematics. Once that is done, we should have the experience to do agood job at less regular or more complicated uses of templates. However, please

    remember that the aims are simplicity, regularity, and performance. You don't prove that

    you are clever by producing the most complicated code.

    Is your prediction regarding concepts based on what happened with meta-programming? What is your stance

    regarding meta-programming in general? Does this paradigm really offer something indispensable or is it sheer

    "cuteness" that has been overstretched?

    Partly, but more directly my guess is based on what happened with class hierarchies and overloading. Every powerful

    new language feature or programming technique goes through a period of overuse. Later, when understanding is better

    diffused in the community, the more reasonable, effective, and maintainable uses become standard practice and the

    "interesting" uses get relegated to experimental uses. I think that there are uses of template programming that go beyond

    both "classical generic programming" and "cute." I think a first attempt of those would be generative programming where the

    template meta-programming techniques are used to generate pretty straightforward code, possibly generic code.

    Would it be correct to say that concepts make type traits less needed (or even redundant) in C++0x? Or do type

    traits still offer capabilities that concepts don't have?

    Concepts can and should eliminate most uses of traits, helper functions for dispatch, and SFINAE overloading.

    Basically, the relationship between concepts and traits is that concepts make overloading simple and straightforward without

    scaffolding (including traits). For example, assuming a suitable set of concepts we can write:

    template

    requires Comparable

    void sort(I b, I e);

    template void sort(C& c) { sort(c.begin(),c.end()); }

    template

    requires Callable

    void sort(C& c, Cmp cmp) { sort(c.begin(),c.end(), cmp); }

    Picking the right sort() is trivial:

    vector v;

    //

    sort(v);

    sort(v.begin(),v.end());

    sort(v,Not_case_sensitive());

    There are uses of traits that do not relate to overloading, such as character_traits, which will remain after concepts become

    universal. However, most of the prominent uses of traits will be eliminated.

    http://www.devx.com/SpecialReports/Article/38864/0/page/1http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_errorhttp://en.wikipedia.org/wiki/Substitution_failure_is_not_an_errorhttp://www.devx.com/SpecialReports/Article/38864/0/page/1
  • 8/8/2019 5147 c++0 Special Report Op

    35/42

    The State of the Language: An Interview with Bjarne Stroustrup

    Have you had a chance to program in any of the newer programming languages (Java, C#, Ruby, and so on)?

    Do you find in them anything that impresses you or worth commending in terms of novelty, engineering merits, or

    simplicity?

    I have tried a lot of languages, including those you mention. I'd prefer not to do language comparisons. Suchcomparisons are rarely fair and even less frequently seen to be fair. However, "simple" is not the first word that springs to

    mind. I note the size of the run-time support involved. I predicted the growth of Java complexity and don't condemn itIconsider complexity an inevitable consequence of serving a large community. The design aims of those languages are not

    those of C++ and vice versa.

    I feel that there is pressure to add to C++ features such as finally, garbage collection, and dynamic array

    bounds checking as an attempt to appease users of other languages. In reality, these features don't fit well into the

    design aims of C++: finally can be replaced by RAII and local classes anyway, GC and destructors are mutually

    exclusive, and runtime bounds checking violates the pay-as-you-go and trust-the-programmer principles. Does C++

    truly need a GC? And more generally, where do you draw the line between borrowed features that are indispensable

    and those that are not?

    There is always pressure to add features. Many people think that I and the committee are just bloody-minded and/or

    stupid not to immediately add their favorite featuretypically a feature they have tried or just heard of in some other language.Often, those same people complain that the committee is adding too many features and that we should remove some of

    those old and ugly "legacy features." Making changes to a widely used language is not easy. There are distinct limits to how

    many changes we can add with a reasonable hope that they will be widely useful, rarely harmful, or confusing, and not

    breaking existing code. People really don't like their existing code to be broken and making significant extensions 100

    percent compatible and properly integrated with all existing and new features can be quite difficult.

    I don't know how to draw a sharp line between worthwhile and frivolous extensions, but I do know that no new feature is

    really "indispensible." I try to evaluate each new suggested feature on its merits and in the context of existing language

    features, library facilities, known problems, and other proposed features. Since the number of new features we can accept islimited, I try to maximize utility, minimize damage, and minimize implementation cost. Each new language feature is an

    intricate puzzle and the more fundamental a new feature is, the more parts of the existing language and existing usage are

    affected and must be taken into account. For example, the new strongly typed enums were relatively easy to design and

    implement because they are an isolated feature, but conversely they are also unlikely to have a dramatic impact on the way

    people design their code and view C++. On the other hand, the new facilities for initialization are likely to impact every user

    and be highly visible in code. On the other hand, their definition touches many points of current usage and definition and is

    therefore at least an order of magnitude harder to design/define than the enumerations.

    finally clauses for try blocks are a minor issue andas you mentionredundant in that we can use RAII. It can even be seriouslyargued that providing finally would lead to uglier and more buggy code as programmers used to it in Java (or whatever)

    found it easier to avoid learning RAII. finally is not on the list of C++0x features.

    The garbage collection issue is not simple. I even think that your question oversimplifies the issueswe need to find a way tocombine GC and destructors. We will not see GC in C++0x, but we will see further work on a design for optional and

    programmer-controlled GC. For C++0x, we will get a definition of what it means for a pointer to be disguised and an ABI for

    deeming areas of memory "not containing pointers" and/or "cannot be collected." The result of these simple guarantees will

    be that existing add-on collectors will be more portable and more effective.

    First, let's clarify the ideals: We want simple and comprehensive resource management. That is, we want every resource

    acquired to be released ("no leaks"). To get that, we need a programming model that is simple to use. A complicated model

    will lead to errors (leaks) when people misuse it or give up on it in favor of (often even more error prone) "home brew"

    solutions. "Comprehensive" is essential because memory isn't the only resource we need to worry about; we need to handle

    locks, sockets, file handles, thread handles, etc.

  • 8/8/2019 5147 c++0 Special Report Op

    36/42

    The State of the Language: An Interview with Bjarne Stroustrup

    We have RAII (for scoped resource use) plus "smart pointers" (for resources that don't have their lifetimes determined by a

    simple scope) as a comprehensive solution. From this perspective, the smart pointer types in C++0x completes the RAII

    technique supported in C++98. Unfortunately, this set of techniques works only where people use it systematically and

    correctly.

    For example:

    void f(int i, char* p){

    vector v(i);

    string s(p);

    //

    }

    Here the storage for elements of v and x are handled automatically by the destructors of vector and string. If X has a non-

    memory resource (for instance, a lock) vector's destructor will release it. This style of use is simple, widely understood, and

    efficient.

    "I consider it obviousthat C++ GC will have to

    be optional (under some

    form of programmer

    control) because some

    programs do not need

    GC (they don't leak),

    some programs cannot

    afford GC delays (not all

    collectors offer real-time

    guarantees), and some

    programs cannot afford

    to include a significant

    run-time support system."

    The reason that GC is attractive to me is that there are projects where I think that "RAII

    plus smart pointers" are unlikely to be systematically and correctly used. Examples areprojects where exceptions cannot be used, projects with a lot of exception-unsafe "legacy"

    parts, projects with components developed in a number of places with different

    programming philosophies and programmer skills, and projects with long-established

    resource management strategies that don't fit the "RAII plus smart pointers" model.

    Typically, such projects are valuable, long-lived, expensive to rewrite, and they leak. Add-

    on garbage collectors have been successfully used to deal with such leaks for over a

    decade. In some cases, the collector is used simply until the leaks can be plugged; in

    other cases, they are used because someone gave up plugging all the leaks. This use of

    GC is sometimes called "litter collection" as opposed to uses where programs leak for the

    convenience of programmers. My guess is that even with the best education based on

    RAII, we will have programs that need litter collection "forever"new ones will be written asfast as old ones are made safe.

    Note that my aim is not to use GC to hide the problems and complexities of resource

    management, but to use GC as yet another tool for dealing with resource problems. This is quite different from the view of

    GC as a panacea. The current C++ techniques for resource management deal more directly with the problem than GC and

    should be used as the first line of defense against resource management problems. One of the strengths of well-written C++

    is exactly that it generates so little garbage. This makes GC in C++ surprisingly (to some) efficient.

    I consider it obvious that C++ GC will have to be optional (under some form of programmer control) because some programs

    do not need GC (they don't leak), some programs cannot afford GC delays (not all collectors offer real-time guarantees), and

    some programs cannot afford to include a significant run-time support system. One of the two major design issues for C++

    GC is how to express this programmer control. The difficulty is to ensure that a program component that relies on the

    absence of GC (for performance, for instance) is never linked with a component that relies on GC. Remember that there is a

    widespread use of dynamic linking and plug-ins so in many contexts whole-program analysis is not an option.

    As you indicate, the other big issue is how to reconcile GC and destructors. If programmers come to rely on GC to collect

    their garbage for them, they might "leak" an object for the collector to recycle even though that object had a non-trivial

    destructora destructor that releases a non-memory resource. For example, given GC, I might use avector v;

    Without providing code to delete the pointers when v is destroyed if I "know" that X does not own a non-memory resource.

    Such code would be brittle because a change to X (for instance, adding a lock member), could make my code leak. In

    general, this problem seems intractable for real-world scenarios involving maintenance of code (adding non-trivial

    destructors) and dynamic linking. However, my impression is that a combination of explicit declarations of destructors

  • 8/8/2019 5147 c++0 Special Report Op

    37/42

    The State of the Language: An Interview with Bjarne Stroustrup

    releasing non-memory resources ("explicit destructors") and heuristics can eliminate a high percentage of real problems.

    Remember that neither of the two "pure" alternatives (no-GC and all-GC) consistently leads to perfect memory management

    either (in the hands of real-world programmers for real-world problems), so the absence of a perfect solution should not

    deter us from providing a good one.

    I know it's a bit early to discuss the farther future of C++ before the C++0x Working Paper is even finalized.

    Still, what are the next stages in the standardization of C++ that will take place once C++0x has been ratified?

    This question reminds me of coming from an 18-hour flight from Los Angeles into the bright morning light in Sydney to

    be met by the question "What do you think of Australia?" That was my first trip down-under so my total experience of

    Australia outside the baggage claim area was about two minutes. That's significantly longer than my post-C++0x experience.

    We are planning some TR (Technical Reports) and there is some talk about a faster revision cycle (about three years after

    the standard). The topics for such TRs (or early revision) are:

    Library components:

    networking (sockets, iostreams over sockets, etc.)

    thread pools

    file system

    lexical_cast

    improved I/O (e.g., faster iostreams, memory-mapped I/O)

    special mathematical functions

    Language features:

    modules (including dynamic libraries)

    garbage collection (programmer controlled)

    Andas usuala host of little things. I just hope that if the committee takes that path it will not be overwhelmed (distracted) by"little things." As usual, implementations of the library components already exist for experimentation and some (for instance,

    the networking library) are already in serious commercial use. In particular, see boost.org.

    You've been designing and improving C++, along with other devoted members of the standards committee of

    course, for nearly 30 years. I assume that the addition of templates to C++ in the late 1980 proved to be the most

    important and successful feature that C++ ever got since you added classes to C in 1979. Is this assumption

    correct? Is there any C++ feature you regret?

    There are things that I would have liked to do better, but who am I to second guess the younger Bjarne? I am no

    smarter than him and he had a better understanding of the conditions at the time.

    In the case of templates, I knew their strengths and I knew their greatest weakness at the time. The first three pages in D&E

    is a lament for not solving the template argument checking problem. In 1988, I knew the problem, but I don't think anyone

    knew a solution that would have been viable in the context of the Draconian requirements of flexibility, generality, and

    performance that were (and are) the bedrock of template use. The design of concepts involved solving genuine research

    problems; we have papers in POPL and OOPSLA to prove that!

    C compatibility has always been a serious problem. The C syntax is horrendous, the conversion rules chaotic, and arrays

    decay to pointers at the slightest excuse.

    http://www.boost.org/http://www.boost.org/
  • 8/8/2019 5147 c++0 Special Report Op

    38/42

    The State of the Language: An Interview with Bjarne Stroustrup

    These are fundamental and constant problems. However, I chose C compatibility (though never 100 percent compatibility)

    as a means of making C++ a practical tool rather than yet another pretty language and so we had to live with it. Even today,

    the overlap between the C and C++ communities and code bases are so large that a serious break of compatibility would

    simply lead to the language community fragmenting. We have to proceed in the usual way: provide superior alternatives to

    ugly and/or dangerous features and hope that people use them.

    In this respect, I read a Slashdot interview in which you say that you would have anyway started off with an

    existing programming language as the basis for a new one, as opposed to starting from scratch. Why not start fromscratch, really? And why start with C?

    Again, I don't have a time machine. At the time, C looked like a good choice for me even though C was not an obvious

    choice then. My guess is that most people would have chosen something simpler and cleaner, such as Pascal or Modula,

    over the flexibility and performance of C.

    Why not start from scratch? Well, at the time, I decided that to build a useful tool with the skills and resources available,

    building on an existing language was essential. I wanted a tool, not a beautiful toy. If I had to do a new language, I would

    again have to evaluate my aims and my resources. Starting from scratch is hard. We always carry our experience with us

    and anything sufficiently different from the familiar will cause teaching problems. People invariably confuse familiarity with

    simplicity. Even Java, which was supposedly designed from scratch according to first principles, chose the ugly and illogical

    C syntax to appeal to C and C++ programmersand Java doesn't even have the excuse of compatibility. Should I designanother language, I guess I would have to try "from scratch" just to get a new set of problems. In that case, I would be very

    sensitive to the idea that there are other forms of compatibility than source code compatibility, such as link compatibility and

    source code transformation.

    Is C++ usage really declining, as some biased analysts and journalists have been trying to convince us for

    years (often not without ulterior motives), or is this complete nonsense?

    It's probably not complete nonsense. C++ use appears to be declining in some areas and appears to be on an upswing

    in other areas. If I had to guess, I'd suspect a net decrease sometime during 2002-2004 and a net increase in 2005-2007,

    but I doubt anyone really knows. Most of the popular measures basically measures noise and ought to report their findings in

    decibel rather than "popularity." Many of the major uses are in infrastructure (telecommunications, banking, embedded

    systems, etc.) where programmers don't go to conferences or describe their code in public. Many of the most interesting and

    important C++ applications are not noticed, they are not for sale to the public as programming products, and their

    implementation language is never mentioned. Examples are Google and "800" phone numbers. Had I thought of a "C++

    inside" logo in 1985, the programming world might have been different today.

    Among the positive signs for C++, I can mention an increase in my email and the number of speaking invitations. At the

    SDWest conference in March, the C++ track was by far the largest, even without counting the "Super tutorial" that I gave

    with Herb Sutter; more than 300 people attended that oneup by a factor of two compared to two years ago. These are, ofcourse, personal and subjective measures, but they fit with other information that I get from innumerable sources in the

    industry (worldwide).

    "We don't know what the

    challenges will be and

    that's C++'s greatest

    strength."

    It's a really big world "out there" and the increase in the number of users of one language

    does not imply the decrease in the numbers of another. I suspect we have reached the

    point where if you can count your users to the nearest million, you don't count as a major

    language. Similarly, I got into a discussion with some friends about how many billions of

    lines of C++ code there were "out there." We concluded that we did not know, but it didn't

    require much thought to demonstrate that the plural was appropriate.

    One simple thing that confuses many discussions of language use/popularity is the distinction between relative and absolute

    measures. For example, I say that C++ use is growing when I see user population grow by 200,000 programmers from 3.1M

    to 3.3M. However, somebody else may claim that "C++ is dying" because it's "popularity" has dropped from 16 percent to 10

  • 8/8/2019 5147 c++0 Special Report Op

    39/42

  • 8/8/2019 5147 c++0 Special Report Op

    40/42

    Timeline: C++ in Retrospect

    C++0x:The Dawning of a New Standard

  • 8/8/2019 5147 c++0 Special Report Op

    41/42

    Timeline: C+ + in R


Recommended