Sorry this is a popular subject (eg here), but I could not find a suitable solution to my problem. Showing code would be too long and confusing, so I am just showing peudo-code; this is a question about design and I am looking for a pattern applicable in C++(11) here.
Goal: I am dealing with multi-dimensional arrays (say, a 4D array containing a vector field), and I want to access array elements with n-D coordinates and dynamic boundary conditions.
Objects:
- Array: contains the data as a 1D array in memory and overloads subscripting (
value_type operator[] (unsigned)
); - Indexer: stores the dimensions of the n-D array, and converts n-D coordinates to 1D indices (
unsigned operator() (Coordinates)
); - Boundary: either transforms n-D coordinates (like a periodic boundary) or returns a default value (eg, null values outside the container).
Requirements
- The coordinates type should be templated (any numeric type should be accepted);
- Boundary conditions can be dynamically modified.
Problem:
Given a n-D container with boundary conditions, I would like the request of a value at given coordinates to look like this:
value_type operator() ( Coordinates )
{
if ( Boundary.transforms_coordinates )
{
/**
* 1) Ensure the coordinates are inbound by applying boundary conditions;
* 2) Use the Indexer to find the corresponding 1D index.
*/
return Array[ Indexer(
Boundary.transform( Coordinates )
) ];
}
else
{
if ( Indexer.coordinates_are_inbound( Coordinates ) )
return Array[ Indexer(Coordinates) ];
else
return Boundary.outbound_value;
}
}
The problem I can't solve is this: if the boundary is dynamically set, its type cannot be a template value, so it needs to be a pointer to a boundary interface. However, this interface cannot define a virtual template method transform
to accept coordinates of different types (let alone a pure virtual one).
I'm guessing there is a fundamental design flaw here, and I would be most grateful if you could show me where, and ideally how to correct it. Sorry as well for the length of the question; this may be solved by design (proto-)pattern I don't know about.