Reputation: 766
I currently have this code:
@interface Matrix4 : NSObject
{
float mat[16];
}
@property (readonly) float mat[1];
I want the property to either give me the mat array or have multiple properties giving me readonly access to mat[1], mat[2], etc.
I current have "Property cannot have array of function type float[1]" as an error message
Upvotes: 2
Views: 1702
Reputation: 108101
As the compiler is telling you, properties cannot have array or function type.
You can manually implement the getter, like
@interface Matrix4 : NSObject {
float mat[16];
}
- (float *)mat;
@implementation
- (float *)mat {
return mat;
}
or you can consider using an NSArray
instead, depending on your requirements. NSArray
is definitely more overweight than a native C array, but it allows you to use properties.
However I suspect you have a design issue: it looks like you are trying to implement a squared matrix, but you are exposing the internal representation, most likely so that the client can set the matrix elements.
You should instead hide the internal representation and only expose methods to perform matrix operations. For instance, you can think of exposing a method which sets the matrix value, as:
- (void)setValue:(float)value forRow:(int)row column:(int)col {
NSParameterAssert(row >= 0 && row < 4 && col >= 0 && col < 4)
mat[row * 4 + col] = value;
}
and one that gives you an element back
- (float)valueForRow:(int)row column:(int)col {
NSParameterAssert(row >= 0 && row < 4 && col >= 0 && col < 4)
return mat[row * 4 + col];
}
and make the mat
ivar private. This gives you also the flexibility of changing the internal representation at will, without breaking the client's code.
The above implementation is also very easy to generalize to a squared matrix of size, by providing a dimension parameter and using a NSArray
or dynamic memory allocation (since variable-length arrays cannot be ivars).
Upvotes: 1
Reputation: 42129
Arrays cannot be return values, so the property cannot have an array type. Instead you must return a pointer, so declare the property as a pointer to the element type of the array:
@property (readonly) float *mat;
Keep the instance variable as float mat[16]
as you have now. Then implement the accessor to return a pointer to the array:
- (float *)mat {
return mat; // array decays to pointer automatically
}
Alternatively, you could have an accessor directly for the individual elements:
- (float)matIndex:(NSUInteger)i {
// maybe check bounds here?
return mat[i];
}
The problem with these approaches is that the information about the size of the array is lost, so you would probably want to put the size of the array in a macro or const
variable. If you need something a bit more object-oriented, make the array an NSArray
and store NSNumber
s in it.
edit: One option would also be to wrap the array in a struct
to preserve the size info, though you still probably want to pass it around by reference:
struct matrixf16 {
float f[16];
};
@interface Matrix4 : NSObject {
struct matrixf16 mat;
}
@property (readonly) struct matrixf16 *mat;
(Also, if I'm guessing correctly that the size is 16 because it's meant to hold a 4×4 matrix, why not make the array float f[4][4]
.)
Upvotes: 5