I'm creating a protocol, and one of the parameters to a method I'm defining is a CMTime*
. I would like to forward declare CMTime
as opposed to including it. However, I've tried @class CMTime
and it complains that it is redefined elsewhere as a different type of symbol. Documentation says it's a struct. I've tried forward declaring it as
struct CMTime;
but it still is complaining that it doesn't know what it is.
Any ideas what I'm doing wrong?
A source compiled as ObjC has the same rules as C in this regard.
A source compiled as ObjC++ has the same rules as C++ in this regard.
@class MONClass;
is a forward declaration of an ObjC type. Do not use it for structs.
struct t_mon_struct;
is a forward declaration of a named C or C++ struct. Do not use it for ObjC types. Technically, the compiler allows you to also forward declare a C++ class as a struct (provided of course the class is also declared in the global namespace).
Thus, the root of the semantics all boil down to C (assuming this is an ObjC translation). I'll stop mentioning ObjC and C++ now.
There are some common sources of complexity here:
- the struct namespace
- the struct's declaration
- avoiding multiple definitions of labels
struct t_mon_struct;
is a forward declaration of a tagged struct. Specifically, that is whose name exists in the struct namespace.
a tagged struct which exists in the struct namespace:
struct t_mon_struct { int a; };
an anonymous struct with a typedef in the global namespace:
typedef struct { int a; } t_mon_struct;
a tagged struct with a typedef in the global namespace:
typedef struct t_mon_struct { int a; } t_mon_struct;
CMTime
is declared as follows:
typedef struct
{
CMTimeValue value;
CMTimeScale timescale;
CMTimeFlags flags;
CMTimeEpoch epoch;
} CMTime;
Specifically, the global typedef label CMTime
is bound to an anonymous struct in the struct namespace, and may not be referenced unless its declaration is visible.
Had CMTime
been declared:
typedef struct CMTime
{
CMTimeValue value;
CMTimeScale timescale;
CMTimeFlags flags;
CMTimeEpoch epoch;
} CMTime;
then you could have gotten by using a forward declaration struct CMTime
:
struct CMTime;
void foo(struct CMTime*);
Since it wasn't declared that way, you'll need to #include
its declaration, or devise a workaround.
The complications worsen when the the struct's typedef is distinct from its tag. You can't bind to or redeclare a typedef (in C). However, you can sneak around it by using the name in the struct namespace -- which some library authors consider as being private.
Just adding typedef
before the struct does the trick for me.
typedef struct CMTime;
If you want the files which have the forward declaration to know about the contents of the struct, they need to either import a header (it can be in multiple places) where it is defined. You can forward declare a struct if you do not need to access its properties, but that is the extent of it.