Sunday, August 07, 2005

Function Type

The keyword typedef facilitates renaming function types in C++. However, typedef is not a mechanism for defining new types. Z++ supports typedef except for functions, which are given more serious consideration.

The C++ support for function-type only slightly extends that of C with regard to methods. Taking the address of a method may be useful in system programming. However, it seems more like coding than an abstraction for developing applications. A method is to be invoked in the form of a message to a particular instance. Therefore, Z++ does not allow defining pointers to methods of a class.

Like C++, Z++ provides extensions to methods, such as const. Indeed, Z++ enforces the throws specification and provides other specifications for global functions, such as threading and signals. The C++ typedef is awkward for such additional specifications.

The Z++ keyword type has a different semantics than its typedef. A name introduced via typedef creates a synonym for the same type (same as C++). However, names introduced via type keyword are treated as new types.

Consider the following definition.

type int MyFunctionType(long, double);

The term type is followed by a function prototype. The identifier MyFunctionType is the name of the function-type being defined. Specifications, such as throws and thread can be added to the prototype, because such specifications are part of type of a function.

One can now declare instances of MyFunctionType and pass them as arguments to function calls. The receiving function (or method) can invoke the instance of function-type that was passed to it.

Consider the following example.

MyFunctionType MyFunction = SomeFunction;

Here, we are creating an instance of MyFunctionType, namely MyFunction, and we are initializing it with a function instance with exact same type, namely SomeFunction. What is important is that the linker will require a definition for SomeFunction. This protects against a confusing defect of passing an undefined function to another function to call.

It may be helpful to discuss the concept of literal as it relates to function-type. When we write down a prototype, we are telling the compiler about two things: a function-type and the name of an instance with that type. This is conceptually similar to the following array declaration.

long my_array[5];

Indeed, the Z++ compiler creates a type named long[5], unless it has done so for an earlier declaration. The compiler then sets the type of my_array to long[5]. In the same vain, a function prototype has a type. A literal value for an instance of a function-type is simply the definition (body) of the function.

From the above observation it should be clear that a function definition may be assigned to two different but compatible function types. Here is an example.

MyFunctionType MyFunction = SomeFunction;
YourFunctionType YourFunction = SomeFunction;

However, we cannot make the following assignment.

MyFunction = YourFunction;

That also means, we cannot pass YourFunction to a call expecting an instance of type MyFunctionType.

Z++ is freely available from ZH Micro.

Labels: , ,