C/C++ Extensions

Home
Projects
Resume
Email

Over my years of programming in C and C++ I've made a wish list of things I'd like to see added or changed. These things mostly concern engineering and simulation programs, but some of it may be useful to others. I've organized the items on my list into functionality categories. The end-goal is to create a set of language extensions that can be enabled or disabled according to the needs of an application, either with #pragma's or command line parameters.

If others take an interest in this and suggest extensions I haven't thought of I'll try and maintain a list of them here. Maybe we can get a new standard going.


Basic Syntax Changes

I had thought of a whole bunch of these once upon a time. Maybe they'll come back to me.

Default Array and Structure Operators

Rationale

This is simply for the purpose of reducing typing. Having default operators would allow objects to be created with a basic and powerful set of functions very quickly. It obscures some of the underlying operations, but they are simple enough that the compiler can generate fast code for them. If implemented properly this shouldn't impact program performance (other than maybe making it faster).

Description

If all of the data elements of a structure have a particular operator defined, then the structure should also have a default operator automatically created that simply calls the operator for each of elements. This default operator is overridden if the operator is explicitly defined for the structure. Obviously since all the elements in an array have the same type, then the above applies to the type of the array. For binary operators, each structure/array must have the same number of elements and in the same order (i.e. int, double is different than double, int). For structures this implies that they're storage equivalent. The size and type of arrays must be known at compile time.

For arrays loops can be used to call the operators on each element. Usage of loop-unrolling should be determined by compiler optimizations.

struct My_struct
{
   double a;
   int b;
   double a;
} structa, structb, structc;

double my_array[], my_array2, my_array3;

//operator= and operator+ are both defined for type double. so the following
//   code calls these operators for each element (assuming the arrays are the 
//   same length)

my_array3 = my_array + my_array2;

// Or...
structc = structa * structb;

// Which evaluates to...
structc.a = structa.a * structb.a;
structc.b = structa.b * structb.b;
structc.c = structa.c * structb.c;

Standard Type Inheritance

Rationale

It would be nice to have the ability to quickly create a new object that is basically the same as an existing object (.i.e int, double, ...) but with a little extra functionality. Not sure what I'd use it for but it sounds like a good idea. A shared memory double for instance.

Description

Allow new types to be inherited from the standard C/C++ types.
class my_double : public double
{
   ...
};

Masked Boolean Operators - Added 14 Apr 2004

Rationale

In some cases not all bits are relevant in a boolean operations. Some processors have instructions that either operate on a subset of the operand bits or somehow change their behavior based on a mask/control operand. Currently neither C nor C++ have any mechanism for directly making use of this functionality. It can only be approximated by beforming bitwise masking operations before the intended boolean operation. A compiler that can understand the concept of masked boolean operators could conceivably make use of the functionality afforded by supporting processors.

Description

Boolean operators that work through a set of mask bits. Instead of comparing all of the bits in the operands, compare only a subset of them as indicated by the mask bits.

For instance, to compare the upper half of two bytes without regard to the 4 least significant bits currently requires something like (a & 0x0F) == (b & 0x0F), which performs two bitwise AND operations before calling the equality operator. The same operation could be performed in a single instruction on some processors, however the compiler has no way of knowing that it should use the single instruction instead of multiple instructions. Boolean operators that accept a third argument would provide the compiler with the needed information and allow it to generate more optimum code.



Branching Instructions

Matrix Switch

Description

A switch statement that selects case statements to execute based on two (or more?) independent inputs. A given case statement is selected if its associated value matches both arguments to switch. If the case statment has two associated values then both must match its corresponding argument.

switch(a,b)
{
   case 3: break;   // Both a and b must equal 3
   case 2,4: break; // If a==2 and b==4
   case 2..4,1..6: break; // If 2<=a<=4 and 1<=b<=6
}

Mathematics Extensions

Number Types

These are aggregate number types that I would like to see supported in a compiler. I know libraries for these things exist, I've even made my own (See my Projects page), but i've always had to treat them as either structures or arrays. Having in-compiler support for these would help standardize their implementation and make it easier to write science and graphics applications that make extensive use of vectors and matrices. A few quick examples:
double vector3 vec;  //An object with three elements of type double
int vector2 v2;      //An object with two elements of type int
vector3 vec3;        //Use default data type (set with a #pragma)

vec = <1,2,3>;       //Assign a value to each element
v2 = (4,5);          //Maybe use parenthesis instead of angle brackets?

//Addition of constants
vec = <1,2,3> + <4,5,6>; //So vec = <5,7,9>

vec[0] = 1;      //Assign a value to the first element of the vector
//which is equivalent to
vec.x = 1;

vec = <1,v2>;    //Composite assignment
If the compiler supported such a notation then you could pass a constant triplet (or any of these other types) as a single element in a function call without having to expicitly make an object, just like the currently supported types. i.e.
void myfunc(double a, vector2 double vec);
...
myfunc(2,<3,4>); //This passes a const double and a const vector2 double
as opposed to
vector2 vec2 = {3,4};
...
myfunc(2,vec2);
From an assembly point of view the previous two code fragments probably look about the same, but the first fragment is shorter and easier to write.

Default Storage Types

As implied in the first example there is a default storage class associated with each of these types that is assumed if a storage type is not specified. The default is to have no default so that it can be set on a per-module basis using #pragma's. The rationale for this is that many programs may consistently use one type of vector(etc...), having a default type could save a lot of typing (no pun intended).
#pragma def_type vector3 double //Set default type to double
Whether or not the operations performed on these types operations are inlined could be decided by compiler optimizations. Obviously some of the simpler operations (like vector addition) are conducive to inlining, while more complex ops (like matrix inversion) probably shouldn't be inlined.

Scalar

This type doesn't really do anything. Its just here for completeness. Specifing it just invokes the default type assigned to scalars (unless a storage type is explicitly given).

Complex Full Specification

This is the standard complex number type. It supports all of the regular operations on complex numbers. It has two elements (r,i) or (real, imag) that correspond to the real and imaginary parts of the complex number.
complex < storage_type > < token >

eg.

complex double mycomplex;

Quaternion

quaternion < storage_type > < token >
Similar to complex but with four elements (x,y,z,s) which can also be accesed as (u,s) where u is a three element vector. The quaternion rotation operator should also be defined for applications that use quaternions to keep track of rotations.

Vector

vector2 < storage_type > < token >
vector3 < storage_type > < token >
vector4 < storage_type > < token >
vector[i] < storage_type > < token >
Has elements (x,y), (x,y,z), (x,y,z,w) for 2, 3, and 4 element vectors respectively. Elements of higher order vectors are accessed as regular array elements. The w element of vector4 should be stored in the same order as the s element of quaternions so that a vector4 can simply be copied into a quaternion and s will equal w.(and vice-versa)

Matrix

matrix3x3 < storage_type > < token >
matrix4x4 < storage_type > < token >
matrix[i][j] < storage_type > < token >
i corresponds to the rows of the matrix and j corresponds to the columns. The idea behind the last line is to allow multi-dimensional (greater than two) matrices to be created and used in a similar manner as multi-dimensional arrays.

Arrays

Arrays of the above types can also be defined in the usual manner.
vector3 double my_vec[5];
Will create 5 3-element vectors of type double for a total of 15 doubles.
vector3 int my_vec[5][5]; //5x5 array of 3 element vectors of type int
matrix[3][3][3] int my_matrix[5][5]; //5x5 array of 3-D matrices

Polar Coordinates

Support a polar coordinate version of the above vector and complex types. This really only affects the operators defined for the object, changes the element names to something more polar oriented, and allows the elements to have different units (if units are being used, see below). I'm still working on the notation for this, suggestions are always welcome. I don't know if there is a polar version of quaternions, but if there is it should be supported as well.


Scientific Extensions

Units Checking

< unit_type > < number_type > < storage_type > < token >
Since I do a lot of programming that deals with engineering principles I often encounter bugs that arise from forgetting which units I had assigned to a variable. And let me tell you, those are some hard bugs to track down. I'd really like a compiler that can keep track of units in a similar fashion as normal type-checking. That is, I want to be able to do something like this:
myfunc()
{
   meters int x;
   meters double length; 
   radians double rad;
   ...
} 
And then have it warn me if I do something stupid like
rad = length;
Naturally I'd also like the compiler to be able to inline unit conversions in the same manner as type conversions. i.e.
double sin(radians double x); 
degrees double theta; 
radians double radtheta;
... 
double a = sin(theta);  //The compiler automatically converts theta to 
                        //   radians
theta = radtheta;       //And here it converts radians to degrees
Should any of the new number types I suggest in the Mathematics Extensions section ever get implemented then they should also support unitchecking.
meters vector3 long myvector;
Supported units should include both FPS and SI systems as well as the conversions between them. All of the standard prefixes should also be supported (kilo, milli, etc...)


Brandon Fosdick
Last modified: Tue Jun 13 23:47:57 EDT 2000