Article Discussion
Your C++ Wish List
Summary: C++0x is under construction. Get your licks in while there's still time.
83 posts on 6 pages.      
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: January 1, 2009 6:55 AM by
Vladimir
Posts: 4 / Nickname: robotact / Registered: August 27, 2005 2:15 AM
Re: Your C++ Wish List (Editorial)
August 29, 2005 10:39 AM      
Such scalability may as well result is ambiguity of auto type (so that original proposition also wouldn't work).
zade
Posts: 2 / Nickname: zadechina / Registered: September 28, 2005 2:50 PM
Re: Your C++ Wish List (Editorial)
September 28, 2005 7:04 PM      
I want stl associative container(set,map etc) to be more flexible. code like below:

std::set<T> set_obj;
std::set<T>::key_compare& kc = set_obj.key_comp();
std::set<T>::iterator iter = set_obj.find(x);
*iter = y;
kc.change_param(z);

I can not change the values directly, and i can not get the key compare functor by refrence.In some special cases, I want to change the element value and the key compare functor synchronously, and I ensure the set's ordering is keeped. I can not do that now.

I want the STL change that
Lee
Posts: 3 / Nickname: lpowell / Registered: October 3, 2005 8:06 PM
Re: Your C++ Wish List (Editorial)
October 4, 2005 2:38 AM      
Introduce an interface keyword that eliminates the hazards of downcasting in a multiple-interface class hierarchy (without requiring RTTI overhead or the use of dynamic_cast). Here's how it could be implemented:

An interface is defined as a struct that cannot contain any non-static data members. All non-static interface methods are virtual. Static data members and static methods are allowed, and constructors and destructors can be optionally defined.

Multiple interfaces could then be added to a virtual base, single-inheritance class hierarchy without requiring more than a single vtable pointer in each base and derived class runtime structure. The vtable pointer for each interface would be a component of each of the class vtables rather than a component of each object instance.

The advantage is that we could retain the runtime efficiency and reliable downcasting properties of single-inheritance class hierarchies, while taking full advantage of the flexibility of multiple interface inheritance. The only drawback would be the small runtime and code size overheads of the additional level of indirection required to reach interface methods. But since interfaces are intended for module encapsulation rather than efficiency, this would be a minor price to pay.
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: Your C++ Wish List (Editorial)
December 6, 2005 9:24 AM      
The most important things are:

1) type inference. The keyword 'auto' can be used (already suggested).

2) garbage collection. I am surprised no one has mentioned it. The keyword 'gc' could be used in front of a class. For example 'gc class Foo {}'. Classes derived from garbage-collected classes would automatically be garbage collected.

3) threads. It goes hand-in-hand with gc.

4) lambda functions. It makes a great difference in language usability.

5) no header files. You heard it right: a new way to compile source files and have headers extracted automatically from them.

Well, with all the above, C++ will be like D, would it not? :-)
George
Posts: 1 / Nickname: gtt / Registered: March 22, 2006 6:12 AM
Lists of types and ability to apply them at compile time.
March 23, 2006 7:42 AM      
One thing I end up doing a lot in our system here is using the preprocessor to instantiate virtual functions when using the Visitor pattern on a large tree heirarchy, and I'd like to propose an extension to templates that might have applicability elsewhere. In the below example, I'm not particularly suggesting a syntax or any keywords or anything. I'm merely using some things that look like keywords and syntax to get the _concept_ of this across. If there's a better or more succinct way to do it...I'm not a language design expert. ;^)

Let's say I have a heirarchy of tree nodes:

class Visitor;
 
class Base { ... };  // This one is abstract.
class A : public Base
{
    ...
    Base& traverse_left();
    Base& traverse_right();
    ...
};
class B : public Base
{
    ...
    Base& traverse_down();
    ...
};
class C : public A { ... };
class D : public A { ... };
class E : public B { ... };
class F : public Base { ... };
class G : public F { ... };
class H : public F { ... };
class I : public F { ... };


(Assume that I've declared:
    void accept(Visitor& v);

in every class above.)

I'd like to be able to divide this heirarchy into groups of types:

type_group SimilarToA = { A, C, D };
type_group SimilarToB = { B, E };


or even better:

type_group SimilarToA = { A, has_base_class(A) };
type_group SimilarToB = { A, has_base_class(B) };
type_group SimilarToF = { F, has_base_class(F) };
type_group AllTreeNodes = { has_base_class(Base) };


Then, let's say I was doing some visitors, I would like to be able to do apply these type group at compile time:

class Visitor
{
    // "apply<List as Name> { code } " would cause the
    // compiler to generate code in a fashion similar to
    // a template, replacing Name in the code between the
    // braces with each name from the list in succession.
    //
    // So the following clause would expand to:
    //
    //   virtual void Visit(A&) = 0;
    //   virtual void Visit(B&) = 0;
    //   ...
    //   virtual void Visit(H&) = 0;
    //   virtual void Visit(I&) = 0;
    //
    apply<AllTreeNodes as T>
    {
       virtual void Visit(T&) = 0;
    }
};


Then I can define traversal (and let's assume it's different for the different classes above):

class TreeTraversal
{
    // Leaves don't traverse.
    apply<SimilarToF as T>
    {
       virtual void Visit(T& n) { }
    }
 
    // A nodes traverse to the left then the right.
    apply<SimilarToA as T>
    {
       virtual void Visit(T& n)
       {
          n.traverse_left().accept(this);
          n.traverse_right().accept(this);
       }
    }
 
    // B nodes traverse down.
    apply<SimilarToB as T>
    {
       virtual void Visit(T& n)
       {
           n.traverse_down().accept(this);
       }
    }
};


One might define a design rule using this facility:

template<class Base>
class MustVisitAllA : public Base
{
    apply<SimilarToA as T>
    {
       virtual void Visit(T&) = 0;
    }
}


And then when compiling a class that inherits from a concrete instantiation of the rule, you'll be forced to implement all the A visits.

One could see that if there were a lot of subclasses of visitor, then this technique could be used quite well to generate methods in them. Right now, to do something similar to the above, I have to use the preprocessor, with all the ugliness and debugging difficulty that this entails. It has been worth it as I probably have a 10:1 ratio of generated methods vs. methods that I have to write (and debug) in our application.

I know that the example I give of use of this is specific to my particular design, but I believe that the ability to apply a list of types to the generation of a section of code arbitrarily as above would be a powerful and useful addition to the language. I don't currently know of a way to generate similar memeber functions (or certain other things) without using the preprocessor.

Thanks for your time. Let me know if this is of any interest.

--
George T. Talbot
Jennifer
Posts: 3 / Nickname: semantic / Registered: May 21, 2006 3:47 AM
Re: Lists of types and ability to apply them at compile time.
May 21, 2006 9:33 AM      
I realise I am joining in 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 than
the copy constructor (in this regard) 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.


4. Virtual inheritance
This is probably pie in the sky, but this *is*
a wish list.

What:
Make virtual inheritance the deault when there is
diamond-like inheritance. (For tree-like inheritance
or non-diamond multiple inheritance there should be no
change compared to today.)

Why:
It does not matter that the current default is faster,
since it is not generally possible to model multiply
ineherited diamond types correctly without virtual inherithance.

If there is any need for the faster way of implementing
them, let it be indicated by a keyword (instead of the
other way around).
Jennifer
Posts: 3 / Nickname: semantic / Registered: May 21, 2006 3:47 AM
Re: Lists of types and ability to apply them at compile time.
May 21, 2006 11:03 AM      
I forgot one thing related to point 1. Default constructor

1.5 equality

What:
For two objects (a and b) of a type T where the copy ctor
is defined, the frestanding:
bool operator == (const T& a, const T& b)
should also be defined, if all subobjects (members/bases)
can be compared with '=='. The return value should be the
and ('&&') of applying '==' to all subobjects for a and b

return a.subobj1 == b.subobj1
&& a.subobj2 == b.subobj2
:
:

Why:
The most important property for a value is that it can be
compared for equality to another value of the same type.
Since equality for aggreagates/composites of well behaved
subobjects can be trivially defined (even though it can be
cumbersome / error prone to do manually over and over again)
the compiler should define operator== if it can and the copy
constructor is defined.

The easiest way to inhibit this, without explicit language
support, is probably to have a member or base that does not
have builtin== or operator== defined. One could for example
inherit from a noequaality class, that is defined in so that
there is no '==' for it.

It is somewhat similar to what you need to do if you want to
inhibit copy ctor and copy assignment, in the case that you do not have a value class.

If you have a value class, the addition of the insistent
default ctor and the operator== will really make a
difference in how easy it is in the langauge proper to
create well behaved value classes from well behaved
subobjects.
Erik
Posts: 2 / Nickname: nimnimnim / Registered: November 13, 2006 8:06 AM
"conditional type" definition
November 13, 2006 3:09 PM      
Using several different external libraries, ie. a rendering engine and a physics engine data types such as Vector, Quaternion etc will be communicated between one library, your gamecode and the other library(ies).

In my case it means cast incompatability as the libraries I'm involved with have no special cooperation.

So this leaves me with incompatible Vector3 and Quaternion types which I atm have two of (but what if I had 3?)..

This means I need to either make a quite bloated and inefficient takesAllCastsAllClass of these types or write global functions for assignment and casting between these types. (consider this: libAQuat * libBQuat * libCQuat; it would need two temporaries for just this operation.)

But if there was a way to define a conditional type like this:

conditional_class GenericQuaternion
{
public:
//and maybe this too? more questionable though
conditional_type real
{
float,
double
};

//has these variables conditions
real w, x, y, z;

//and possibility to declare function conditions
// void normalise(void);
};

or in any other syntax defining a conditional type with the conditions that it must have the variables w, x, y and z of type float or double.

and the possibility to define conditions of must-have functions (also allowing conditional types and class-types as parameter types) would also be needed for this to be fully usable.

That would be sufficient for many perpouses!.. these libraries could in every method possible use this conditional type instead of their own type in function definitions.

Like in the Quaternion class of the Ogre3D graphics library.

Quaternion operator* (const Quaternion& rkQ) const;
(note it's not virtual and mostly they aren't)
instead:
Quaternion operator* (const GenericQuaternion& rkQ) const;

and the compiler would compare conditional_types by their definition when building a project using an external library.

Now conditional types should probably not be allowed as return types and wouldn't be needed if all libraries used conditional types for method parameter types but maybe cast operators of conditional types wouldn't be evil either.

Then finally I guess the author of each library could use #ifdef USE_CONDITIONAL_TYPES so I hope there's nothing evil about this concept.

If it'd be deemed a risky way of coding please consider the performance improvements it could mean for ie. a game using the mentioned libraries which as it stands now makes maybe one or several Quaternion temporaries for each game object every frame when gathering object orientation from the physics engines object and passing it to the rendering engines corresponding scene node (and in between some arithmetic operators are likely to be called on either of these types).
Erik
Posts: 2 / Nickname: nimnimnim / Registered: November 13, 2006 8:06 AM
Re: "conditional type" definition
November 13, 2006 3:16 PM      
oh and within a conditional_class declaration the conditional methods should be allowed to have conditional types (conditional_class types or conditional_type's) as return types but not within a regular class or struct definition.
lemon
Posts: 11 / Nickname: lemonhead / Registered: November 23, 2006 0:53 AM
Re: Your C++ Wish List (Editorial)
November 23, 2006 0:28 PM      
I posted these wishes in another thread (A Brief Look at C++0x), but obviously they belong here!!


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'). I want to suggest different possible syntax for that (it would be enough to have one).

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; 
 
    // possible, but doesn't derive anything
    struct {
        void foo() {foo_C();}  // not possible - nowadays, c.nested has no access to the members of c.
    } 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.
lemon
Posts: 11 / Nickname: lemonhead / Registered: November 23, 2006 0:53 AM
Re: Your C++ Wish List (Editorial)
November 23, 2006 0:49 PM      
6. class modules. A struct that cannot have instances, pointers, references, and does not even have a size ! It is not a data type, it only serves to compose a bigger class. Like that.

module A {
    float member_A;
    virtual void foo_A_v()=0;
    void foo_A() {foo_C("A");}
};
 
module B {
    int member_B;
    virtual void foo_B_v()=0;
    void foo_B() {
        foo_C("B");
        member_A = member_B;
    }
};
 
struct C : A, B {
    void foo_C(char* s) {cout << s;}
};
 
A* a=0; // not possible!! no pointer A* allowed!
C* c;  // this is allowed.


The effect should be similar as copying the code of A and B into the declaration of C. Of course C needs to support the method foo_C(char*), otherwise the compiler will complain.

The construction of vtables etc will all happen in C, not in A or B. Therefore, C needs only one vtable pointer.

Something like that can be achieved nowadays with the Barton-Nackmann trick (but this doesn't affect the vtable), but I think my version is much better understandable.
lemon
Posts: 11 / Nickname: lemonhead / Registered: November 23, 2006 0:53 AM
Re: Your C++ Wish List (Editorial)
November 23, 2006 2:10 PM      
About modules.
- a module can use members of the child class.
- a module itself can be derived from any other module or class. (I don't see any problems with that!)
- a module is not a data type.
lemon
Posts: 11 / Nickname: lemonhead / Registered: November 23, 2006 0:53 AM
Re: Your C++ Wish List (Editorial)
November 24, 2006 3:40 PM      
Another way to define modules

// version (i)
modular class A {
    modular void foo_B()=0;
    void foo_A() {foo_B();}
};
 
struct B0 : A {
    void foo_B() {cout << "cat";}
};
 
struct B1 : A {
    void foo_B() {cout << "dog";}
};
 
struct C1 : B1 {
    void foo_B() {cout << "two dogs";}
};
 
int main() {
    B0().foo_A();  // writes "cat"
    B1().foo_A();  // writes "dog"
    C1().foo_A();  // writes "dog" or "two dogs" ?? (*)
}


Here the modular keyword is somehow the same as the virtual keyword, but for compile time polymorphism.

(*) Obviously, this mechanism needs more thinking!!

// version (ii)
module A {
    void foo_B() {Final::foo_B();}  // 'Final' keyword to specify the implementing class. 
};
lemon
Posts: 11 / Nickname: lemonhead / Registered: November 23, 2006 0:53 AM
Re: Your C++ Wish List (Editorial)
November 25, 2006 5:21 AM      
Class Modules and enhanced member objects - what are they good for?
- class modules can be used instead of the curiously recurring template pattern (crtp).
- compared to the crtp, class modules reduce the number of classes to compile.
- compared to the crtp, class modules allow multiple inheritance without the typical drawbacks.
- member objects of an anonymous class no longer need to store a reference to the enclosing object.



Example 1) Efficient way to define properties similar to C#.

// could be done with curiously recurring template patterns instead of class modules.
template<typename value_type> module M_T {
    Final& operator += (value_type value) {
        Final::set(value);
    }
    ...  // the entire interface
};
 
struct C {
    int update_count;
    M_T<float> weight {  // anonymous class derived from the module!
        float val;
        void set(float value) {
            val=value;
            ++update_count;  // easy access to enclosing class
        }
        float get() {return val;}
    };
};
 
int main() {
    C c;
    c.weight = 9.2f;
    c.weight += 3f;
}



Example 2) Workaround for the lack of virtual function templates

template<typename T> module M_Base_T {
    virtual void foo_v(T)=0;  // overloading instead of template argument
};
 
struct Base : M_T<C0>, M_T<C1>, M_T<C2> {  // only one vtable pointer needed !!
    template<typename T> void foo() {foo_v(T);}
};
 
template<typename T> module M_Imp_T : public virtual Base {
    virtual void foo_v(T) {
        Final::foo_imp<T>();
    }
};
 
struct M_Imp : M_Imp<C0>, M_Imp<C1>, M_Imp<C2> {
};
 
// user code
struct MyClass : M_Imp {
    template<typename T> void foo_imp() {
        ... // implementation
    }    
};




It's maybe too late for these suggestions to get into C++0x. However, I'm really missing at least the enhanced member objects, which would be very easy to implement imo!
lemon
Posts: 11 / Nickname: lemonhead / Registered: November 23, 2006 0:53 AM
Re: Your C++ Wish List (Editorial)
November 27, 2006 4:39 AM      
Example 3) A little state machine (with performance benefits compared to if-else, if there is a higher number of states)

struct SimpleStateMachine
{
SimpleStateMachine() {current_state=state_A;}
void step() {current_state->step();}
private:
struct State {
virtual void step()=0;
} * current_state;
State state_A { // derived from struct State
virtual void step() {current_state=state_B;}
};
State state_B { // derived from struct State
virtual void step_v() {current_state=state_A;}
}
};
83 posts on 6 pages.