// a collection definition
class Counter[] {
int elt_total; // an element member variable
int Counter[]::total; // a collection member variable
public:
Counter(void); // an element constructor
Counter[](void); // a collection constructor
int count(int); // element member functions
int elt_sum(int);
int Counter[]::sum(void); // a collection member function
};
This declaration creates two classes: the Counter[] collection type and the Counter element type. The Counter element has just one field: elt_total. The Counter[] collection consists of a linearly addressable set of Counter objects and one field of collection state: total. Counter[] has the member function sum, and Counter has the member functions count and elt_sum. Notice that the collection declarations are qualified and the element declarations are not; all unqualified declarations in a collection definition belong to the element type, and declarations for the whole collection must be qualified with the collection type name.
Since collections are classes, derivation is supported for them. It works class-wise so that derived inherits from base and derived[] inherits from base[]. For nested collections, each level inherits class-wise from the corresponding level in the base collection class.
Counter Foo[15]; conc for(int i = 0; i < 15; i++) Foo[i].count(i); cout << Foo.sum();
Note that since there are no syntactic dependencies between the iterations of the conc for loop, the count calls can proceed in parallel. In addition, because the execution of iterations is not specified, the compiler is free to reorganize them for higher efficiency, as parallel compilers traditionally do.
This example illustrates the simplest use of collections: to express data parallelism by simply applying the same method to every element of a collection. This construes data parallelism as object-parallelism as in pC++, a generalization of the vector operations in languages such as Fortran which is the traditional meaning of data parallelism.
Consider the following example template definition:
template<class Constituent>
class MultiSet[]{
private :
Constituent elts[];
int elt_count;
public :
// constructors omitted
Constituent add_elt(Constituent elt){
return elts[elt_count++] = elt;
}
int find_elt(Constituent elt){
return MultiSet[]::this->find_elt(elt);
}
int find_elt_internal(Constituent elt){
int count = 0;
for (int i=0; i<elt_count; i++)
if (elts[i] == elt) count++;
return count;
}
int MultiSet[]::find_elt(Constituent elt){
int count = 0;
conc for(int i = 0; i < size(); i++)
count += (*this)[i].find_elt_internal(elt);
}
};
The MultiSet abstraction is a distributed multi-set in which different constituents are stored in each collection element. Constituents are inserted into specific elements; looking up an element therefore involves looking across the entire collection. The ability of elements to access the entire collection allows the MultiSet elements to cooperatively implement a concurrent interface to the abstraction: multiple calls to add_elt can proceed simultaneously when called upon different elements of the collection, as in:
MultiSet<int> set[17];
int stuff[100];
conc for(int i=0; i<100; i++) {
set[i%17].add_elt(stuff[i]);
}
Note that the use of templates and collections allows the MultiSet to be a reusable abstraction that presents a concurrent interface. This combination makes libraries of concurrent abstractions possible.
This approach to collections, which integrates arrays into the object model, also divorces arrays and pointers. C++ vitiates pointers, allowing arithmetic only within C++ aggregates (i.e. objects and arrays). ICC++ forbids using pointers as arrays, replacing them with array-typed references. This choice not only allows more precise program analysis, it also provides uniform typing for multidimensional arrays. In addition, it allows the implementation to distribute collections without complex implementations of pointer arithmetic, but it necessitates some changes to C++ syntax. The type [ ] must be used instead of type * wherever an array variable is declared or defined. Two dimensional arrays must be declared using type [ ][ ], and analogously for higher dimensionalities.