Article Discussion
A Brief Look at C++0x
Summary: Bjarne offers a sneak peek at the next version of standard C++ ("C++0x") which should be complete by 2009.
151 posts on 11 pages.      
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: November 23, 2006 8:19 AM by lemon
Joel
Posts: 1 / Nickname: redmjoel / Registered: December 19, 2005 7:09 AM
Re: A Brief Look at C++0x
January 16, 2006 9:08 AM      
Here's my top 3 wish list item:

1. Lambdas -- at least at the level of Boost::Lambda
what: A way to pass functions into the STL
why: Without a lambda-ish way of passing a function object into the STL algorithms and containers, there will not be a widespread use of the STL algorithms. Currently, it is a big headache to use the (for instance) std::find algorithms. Much more so than writing your own loops.

2. Garbage collection
what: Automatic resource tracking (as in C++/CLI)
why: Takes the burden of tracking memory away from the programmer if not needed. This is something that C++/CLI has gotten right, and it would be shame to not be able to use it in a wider context. The C++/CLI version doesn't pass an undue burden onto the run-time, as it would only be necessary to run the garbage collecter in code which actually uses the garbage collection keywords. This is something which is easily visible at link-time. It is possible that this could be an "optional" part of the standard, so that places where it is inappropriate would not have to implement it. This would be the case for DSPs for instance.

3. Initialization of collections
what: Support for "vector<int> list = {1, 2, 3, 4, 5};" syntax
why: This is a big headache for both novice users and experienced programmers. The current standard also violates the design goal of making user types equivalent to built-in types.
Aleksey
Posts: 1 / Nickname: agurtovoy / Registered: January 19, 2006 11:47 AM
Re: A Brief Look at C++0x
January 19, 2006 5:29 PM      
> I wouldn't critize Boost for being "modern". I think the
> real problem is that many "boosters" are interested in
> "neat/advanced" libraries rather than in providing
> yet-another, but more standard and usable directly useful
> component.

That's quite an accusation. Do you have any data to support it?

> For example, why weren't boost threads, boost
> sockets, boost XML, boost unicode, and boost files among
> tthe very first boost components?

Because, beleive it or not, building any sizeable domain-specific library that a skilled C++ engineer would be satisfied with actually requires lots and lots of these low-level "neat" libraries [1] that the C++ standard is missing.

[1] Often in the form of both the actual code and the conceptual foundation.

> Such foundation for
> applications are hard and non-glamorous - it takes a major
> effort to get people to create and maintain such
> components.

Right, and, say, Boost.Type Traits, Boost.Graph and Boost.Regex (one of the very first Boost libraries) were a piece of cake, totally glamorous, and took no effort to create and mantain.
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: A Brief Look at C++0x
January 23, 2006 5:28 AM      
Here are some other interesting ideas. I am posting them not as 'things I want', but as interesting ideas for discussion:

1) friend access attribute customized on classes/functions that can have access. Example:


class MyClass {
public:

protected:

private:
int a;

friend(MyOtherClass1, MyOtherClass2, MyFunction1):
int b;
};


2) truly private implementations. The header files will contain 'interface' classes which might or might not have all the members, and the implementation file will declare the actual internal implementation of the class as well as private fields/methods not visible in the header file. Example:


//header file
interface MyTruePrivateClass {
public:
void publicMethod();

private:
};

//implementation file
implementation MyTruePrivateClass {
public:
void publicMethod() {
}

private:
int truePrivateData;
void truePrivateMethod();
};


The compiler should keep a hidden table of object sizes to use with operator new or member declaration, as well as for checking if implementation of object already exists.

3) custom pointer syntax. Example:


template <class T> class SmartPtr@ : _SmartPtrBase {
public:
...
};

template <class T> class WeakPtr^ : _WeakPtrBase {
public:
...
};

//using weak and smart pointers
Foo @foo1 = new Foo;
Bar ^bar1 = new Bar;
(@foo1).data = 5;
(^bar1).data = 5;


4) more functionality in operator new, using a special class new<T>. For those classes that have a specialization of new, it is the New<T> that is called instead of operator new. This will allow various actions on an object not possible now. Example:


class Foo {
};

template <> new<Foo> {
public:
//called instead of operator 'new'
static Foo *operator new(size_t size) {...}

//called instead of operator 'delete'
static void operator delete(Foo *foo) {...}

//called implicitely after object constructor
static void created(Foo *foo) {...}

//called implicitely after object destructor
static void deleted(Foo *foo) {...}
};


The above will allow things like this:

a) performing actions that depend on allocated type; for example registering a finalizer in a garbage collector.
b) performing actions that depend on after constructors have been called; for example, registering an object somewhere, while calling a virtual method of the object (not possible before instantiation).

5) accessing struct/class members with array syntax; operator lengthof that returns number of elements of array/tuple. This is necessary for compile-time introspection. Example:


struct MyStruct {
int field1;
double field2;
float field3;
};

template <> void doSomething(MyStruct *s, int field);
template <> void doSomething(MyStruct *s, double field);
template <> void doSomething(MyStruct *s, float field);

void processMyStruct(MyStruct *s) {
//intrinsic function 'lengthof' returns length of tuple
for(int i = 0; i < lengthof(*s); ++i) {
//using fields of a struct with array syntax; different version of 'doSomething' is invoked for each field
doSomething(s, (*s)[i]);
}
}


6) aspects/introspection by classes for classes. Example:


//my class
class Foo {
public:
void doSomething();
};

//class of class Foo
class<Foo> {
public:
//aspect overloading
void doSomething() {
log << "doSomething was called\n";
Foo::doSomething();
}
};

Foo *foo = new Foo;
foo->doSomething(); //the aspect is invoked, instead of the method.


Very useful for debugging purposes and other operations. With this capability, point #4 above is reduntant, as operator new can be a member of the aspect classes.

7) instance creation by namespace string. Example:


Object *myObject = new "MyApp::MyClasses::Foo"(1, 2, 3);


Useful for loading modules at run-time. The compiler should place an internal array of class information in each executable/library.

8) classes that can be defined/extended on the point of declaration. For example:


class Foo {
public:
virtual void action();
};

Foo *foo1 = new Foo() {
void action() {
printf("subclassed!\n");
}
};

Foo foo2() {
void action() {
printf("subclassed!\n");
}
};

sort(mydata, class MyFunctor() { bool operator ()(int a, int b) { return false }});


Useful for for callbacks, etc.

9) local functions. Example:


void outterFunction() {
int i;

void innerFunction() {
int j = i + 1;
}

innerFunction();
}


It's quite easy to achieve. The inner function's stack should come right after the outter function's stack; think about is as struct inheritance. Stack frames should be dealt with as locally defined structs, and local variables should be accessed as member objects of the function. For example:


outterFunction.i = 5;


Local functions allow for interesting algorithms.

10) formalize CPU context. The standard library should provide a CPU context class as well as methods to get/set CPU context. Since C++ is a high-level language for a low-level environment, C++ should provide such functionality. This functionality will allow for user threads, user multithreaded garbage collection, co-routines, tail call optimization etc. The API should be fairly abstract: the CPU context should be handled as an array of bytes, but also as a struct with named registers. The API should offer the following functionalities:

a) setting and getting the CPU context.
b) getting the stack information (top and bottom address).
c) using the stack: push, pop.
d) setting up the next address to execute.

11) arbitrary length integer, real arithmetic; fractions; ranges. I think the standard library should have those.

12) sets. Like enumerations, but member values can be objects. Example:


setdef MyColor : Color {
Red = Color(255, 0, 0),
Green = Color(0, 255, 0),
Blue = Color(0, 0, 255)
};

setdef Day : const char * {
Sun = "Sunday",
Mon = "Monday",
Tue = "Tuesday"
};


Sets could be used like arrays or enumerations. Example:


MyColor c1 = Blue;
Color c2 = MyColor[2];


The reason sets are useful is the same as enumerations: they limit the chances of using the wrong value (as well as provide names for standard values).
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: A Brief Look at C++0x
January 23, 2006 5:40 AM      
Some new stuff that I just came up with:

1) constructor forwarding. Just as destructors are forwarded, so should constructors. If a derived class has no constructor, then it gets the constructors of the base class. This will make it easier to use the 'inherit from template parameter' pattern. Example:


template <class T> class MyClass : public T {
public:
};

class MyBase1 {
public:
MyBase1(const char *str);
};


class MyBase2 {
public:
MyBase2(double);
};

new MyClass<MyBase1>("aaa");
new MyClass<MyBase2>(3.14);


2) template classes as friends, not only template specializations. Often the need arises for a template class to be friend of a non-template class, but it is not possible with the language as it is now without an intermediate class. Example:


class MyClass {
public:

private:
//make all specializations of MyTemplate friend to this
friend class MyTemplate;
};

template <class T> class MyTemplate {
public:
};
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: A Brief Look at C++0x
January 23, 2006 5:46 AM      
(sorry guys for replying to myself; is there an 'edit' button? have I missed it?)

Yet another one:

1) if a class does not have a parameterized constructor, and the programmer uses a constructing call with operator =, then the compiler should call the default constructor, then the operator =. Example:


class MyClass {
public:
MyClass();
MyClass &operator = (int x);
};

MyClass c = 1;
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: A Brief Look at C++0x
January 23, 2006 6:37 AM      
Nested comments. Some time it is needed to just comment out a piece of code that includes block comments. Example:


/+ nested comments
/* block comments */
//line comments
+/
Dmitriy
Posts: 5 / Nickname: limit / Registered: January 11, 2006 2:08 AM
Re: A Brief Look at C++0x
January 24, 2006 0:14 AM      
> 12) sets. Like enumerations, but member values can be
> objects. Example:
>
>

> setdef MyColor : Color {
> Red = Color(255, 0, 0),
> Green = Color(0, 255, 0),
> Blue = Color(0, 0, 255)
> };
>
> setdef Day : const char * {
> Sun = "Sunday",
> Mon = "Monday",
> Tue = "Tuesday"
> };
>


I think that better to extend enum keyword functionality and trait it as predefined template with one template parameter that denote base type for enumeration constants.
In this case your examples can be rewritten:


enum MyColor<Color>
{
Red = Color(255, 0, 0),
Green = Color(0, 255, 0),
Blue = Color(0, 0, 255)
};

enum Day<const char *>
{
Sun = "Sunday",
Mon = "Monday",
Tue = "Tuesday"
};


It is also solve a problem with exact base type for ordinary enumerations. C++ rules in this aspect is not so easy to remember.


enum A<int>
{
ONE = 1;
};
enum B<unsigned>
{
TWO = 2;
};


Of course enum C {} is also possible. In this case old rules for base type would apply.
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: A Brief Look at C++0x
January 24, 2006 3:02 AM      
Thanks for the reply. Good idea about the enum syntax. Any other comments? anyone?
Dave
Posts: 6 / Nickname: abrahams / Registered: October 6, 2004 10:03 AM
Re: A Brief Look at C++0x
February 21, 2006 9:21 AM      
> One technical problem (that the boosters are trying to
> find a solution to) is that boost is a monolith. This has
> been a problem with outher libraries also, such as ACE.
> For example, say I want to be able to download and use
> just the regular expressions and don't want any other
> library to complicate my system, how can I get just
> boost::regex and what it depends on and nothing else.

First of all, let me acknowledge that Boost has (intentional) internal dependencies. That said, while I'm sure Bjarne didn't mean it that way, most of the above is misleading at best. So let me clear a few things up:

1. Boost is not a monolith in any sense, except maybe that we don't provide separate downloads of individual libraries.

2. As of a year or two ago, Boost's coupling was *nothing like* ACE's. A friend of mine was working for a company that built refactoring software that could graph dependencies. When they threw the technology at ACE, it quickly became known as "the blob": because everything was linked to everything else, you couldn't make out the individual edges in the graph. All you could see was a big black mass. When we did the same with Boost, there were a few small areas that could be improved, but for the most part the dependencies were hierarchical and non-cyclic. I don't know what has happened with ACE recently (things may have improved), but Boost has maintained the practices that resulted in that low coupling.

3. We have a tool that can separate out individual libraries and their dependencies: http://www.boost.org/tools/bcp/bcp.html. So far it has been a little overly conservative, but we are working on ways to make it less so. For example, some dependencies only arise when optional features of a given library are used. We're adding features to make sure that those dependencies are pruned when users don't explicitly request the optional features.

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
Piet
Posts: 1 / Nickname: cyberpoep / Registered: February 23, 2006 11:43 AM
Re: A Brief Look at C++0x
February 23, 2006 4:55 PM      
Sorry for interrupting this discussion but I'm new to C++ and when I saw Bjarne writing an article I thought wow maybe this C++ Genius may know the real C++ Genius http://www.cplusplusgenius.wagoo2.com/

Is there anyone in this forum who knows this guy. Is he really a genius? I wish he would upload the software he's refering to on his downloads page.

Ok you can continue discussing this new C++ thing, but please let me know if you know anything about this guy.

Thanks
Dave
Posts: 6 / Nickname: abrahams / Registered: October 6, 2004 10:03 AM
Pass By Name
March 4, 2006 8:32 PM      
> optional C++ extensions to macro system
> what: Add extensions to the preprocessing macro system
> such that old C macros work, but that programmers can take
> advantage of macros defined at a "conceptual level"
> instead of at a textual level -- perhaps by adjusting the
> parse tree instead of the source code.
> why: While C++ features like templates and const data can
> elliminate the need for many C macros, some programmers
> like the possibility of adding keywords to their own
> programs, without being constrained by template syntax,
> etc. This generalized construct sould then be used to
> define "pass by name" or similar wishes.

FYI, there's a library solution for "pass by name:" http://www.boost.org/libs/parameter
Hillel
Posts: 1 / Nickname: thesim / Registered: March 21, 2006 2:01 PM
C++
March 21, 2006 7:19 PM      
Hello hello. Is this thing still on?

- Re, lambdas: Does anyone use bind()?

- Re, threads: A reliable model of threading in C++ will not exist until exceptions and cancellation are unified. I almost fear it is too late for this in the general population though, due to the entrenched legacy behavior on most C++ platforms.
Jennifer
Posts: 3 / Nickname: semantic / Registered: May 21, 2006 3:47 AM
Re: A Brief Look at C++0x
May 21, 2006 8:46 AM      
I realise I am joining in *very* late in the discussion,
but here goes:

1. default constructor

what:
The default ctor should be automatically defined
(if the user does not provide one) *even if* the user
provides other ctors.

why:
C++ supports value oriented programming (where classes
can be used in the same way as builtin types), but
having the default constructor behave differently
(in this regard) than the copy constructor is confusing
(as to why) and unneccessary.
If you do not want a value class, inhibit
the dflt ctor the same way you would inhibit the copy ctor.

2. hiding vs overloading

What:
A function "f" (with unique argument types) in a class
"Derived" should not hide other f in the base class "Base".
It should overload the other f in the base class.

Why:
Every time I have declared a "f" in a subclass
(with other f in "Base", it has been with the intention
to overload. Never to hide. Hiding violates LSP.


This behaviour in C++ has always surprised me,
and I have never felt that it has been right
(in 15 years of C++ programming).
I know about "using Base::f" but it seems better to have
that behaviour as default (that is, overloading).


3. overloading resolution

What:
When looking for candidate (member) functions,
do not consider functions that I can not access
(eg. private functions). Only consider functions that are
accessible to me at that point.

Why:
The whole idea of "separating interface from implementation"
is about not needing to the implementation. It is not very
robust if suddenly I can not compile a piece of code because
the implementation needed and declared (in the class)
a new function that happens to be the best match
*if I could have used it*.

I know about the pimpl idiom, but this should have the
(in my vew) correct behaviour for the "basic" class usage
already.
John
Posts: 1 / Nickname: bismuth / Registered: August 17, 2006 3:09 AM
Re: A Brief Look at C++0x
August 17, 2006 7:34 AM      
Not sure if this has been mentioned before, but how about adding the ^^ as a logical exclusive OR boolean operator?

It would complete the set, along with the current || and &&

Having &&= ||= and ^^= would be nice too.

Yes, I know you can do all of this with the binary operators, but wouldn't it be better to do it properly?
lemon
Posts: 11 / Nickname: lemonhead / Registered: November 23, 2006 0:53 AM
My Wishes
November 23, 2006 8:15 AM      
1. Variadic templates
(as suggested and discussed elsewhere)



2. Anonymous nested objects (here: c.nested) with access to the containing object (here: c of type C). It should be possible to derive their type from a base class (here: 'Base').

struct Base {
    virtual void foo() {}
};
 
struct C {
    void foo_C() {}
 
    // not possible in c++ nowadays
    Base {
        void foo() {foo_C();}  // nowadays, c.nested has no access to the members of c.
    } nested; 
 
    // not possible in c++ nowadays
    Base nested {...}; 
 
    // not possible in c++ nowadays
    struct {...} nested : Base; 
 
    // not possible in c++ nowadays
    struct : Base {...} nested; 
 
    // not possible in c++ nowadays
    struct {...} nested; 
} c;
 
Base* b = c.nested;
b->foo();

To access the members of c, c.nested doesn't need to store a reference. The adress difference of c and c.nested is the same for any object c with type C, so accessing c.foo_C() would technically be no problem.

(Nowadays, this can be achieved using the barton-nackmann trick and multi-inheritance, but that's not a nice solution)



3. The same for nested functions - they should as well be able to access other members of the containing class or function.



4. A "This" keyword to identify the type of "*this".

template<... ... ...> class A {
    typedef A<... ... ...> This;  // too clumsy, should be done by the compiler!!
};




5. exit loops with a break statement with return value

for(...) {
   ...
   if(..) break end_of_file(i);
   else if(..) break end_of_file(i+5);
   else if(..) break found_error("parsing_error");
   ...
   if(..) break found_error("mature content");
}
 
cout << "normal_break" << endl;
 
label end_of_file(int line_number) {
   cout << "end of file reached in line "<< line_number << endl;
}
 
cout << "normal break or end of file finished" << endl;
 
label found_error(char* message) {
   cout << "found error " << message << endl;
}
 
cout << "normal break or eof or found an error" << endl;

These labels are similar to nested functions. The difference is, when they are finished, execution will continue in the line where the label block ends.

The same could be achieved with helper functions, but then the code would be scattered in places where it is hard to find.
151 posts on 11 pages.