![]() | |
![]() ![]() |
![]() | Imperfect C++ Practical Solutions for Real-Life Programming By Matthew Wilson |
Table of Contents | |
Part Three. Language Concerns |
Chapter 18. TypedefsThe typedef specifier in C and C++ provides a new name for a given type. Two classic uses in C are in removing confusion when using function pointers and reducing typing effort when using structures. Consider the code without typedefs in Listing 18.1. Listing 18.1.// Info.h struct Info {}; int process(int (*)(struct Info*, int*), int*); // client_code.cpp int process_forwards(struct Info*, int); int process_backwards(struct Info*, int); int main() { struct Info info; int (*pfn[10])(struct Info*, int); . . . for(i = 0; . . .; ++i) { pfn[i] = . . . Contrast that with the code in Listing 18.2 that uses structure and function pointer typedefs. Listing 18.2.// Info.h typedef struct Info {} Info_t; // struct typedef typedef int (*processor_t)(Info_t*, int*); // fn ptr typedef int process(processor_t , int*); // client_code.cpp int process_forwards(Info_t*, int); int process_backwards(Info_t*, int); int main() { Info_t info; processor_t pfn[10]; . . . for(i = 0; . . .; ++i) { pfn[i] = . . . I hope you'll agree that the latter form is far more readable. It is also legal (C++-98: 7.1.3,2) to redefine the name of any type (within the same scope) to the type to which it already refers. This is pretty pointless for many types—for example, typedef int SInt; typedef SInt SInt;—but it is very useful for removing the need to type struct or to remember the association between a given structure typedef and the actual structure for which it acts as a synonym: typedef struct Info {} Info; // synonym of itself . . . int main() { Info info; . . . In fact, C++ differs from C in not requiring that a class type be prefixed with its class key (the class/struct/union bit; C++-98: 9.1). This gives a cleaner and more succinct form without the typedef: struct Info {}; Info info; But if you want C compatibility, it's better to define a synonym via a typedef. Where typedefs have really come into their own in C++ is in the fact that they can be used to define member types within classes and namespaces, which underpins a great deal of generic programming, including the traits mechanism, as shown in Listing 18.3. Listing 18.3.template <typename T> struct sign_traits; template <> struct sign_traits<int16_t> { typedef int16_t type; typedef int16_t signed_type; typedef uint16_t unsigned_type; }; template <> struct sign_traits<uint16_t> { typedef uint16_t type; typedef int16_t signed_type; typedef uint16_t unsigned_type; }; This chapter takes a close look at typedef, at some of the dangers of its use, and distinguishes between the use of typedef for conceptual type definitions and contextual type definitions. Finally, it introduces the concept of True Typedefs, and illustrates a template-based implementation of it that can be used to provide a stronger degree of type safety than is afforded by the language as it stands. ![]() |
![]() | |
![]() ![]() |