TITLE: typedefs as tags and class labels (Newsgroups: comp.std.c++, 27 May 98) OLIVA: Alexandre Oliva >> The general rule is that typedef-names that refer to classes can be >> used as class-names, but not in elaborated-type-specifiers nor as >> constructor or destructor names, i.e.: >> >> typedef X W; >> >> struct W x; // ill-formed >> W y; // ok >> >> X::W() {} // ill-formed >> >> W::~W() {} // ill-formed >> >> W::~X() {} // ok, IMHO KUYPER: James Kuyper >Where does it say that? Why does it say that? How do you go about >constructing or destroying an object of a class that your code knows >about only through a typedef in someone else's code? CLAMAGE: stephen.clamage@sun.com (Steve Clamage) The rules on typedefs and name lookup say that. See especially draft standard sections 7.1.3, 12.1, 12.4, and 3.4. A typedef is an alias for a type. When a typedef name is used, it resolves to the underlying type. Hence, typedefs are described as "transparent". A typedef is not a tag, a "tag" being the label on a class or enum. Thus, "struct W" above is ill-formed, because W is not a tag name. The original C++ definition said some things about the names of constructors and destructors that caused confusion and definitional problems. The draft standard resolved those problems while retaining the desired properties by saying that ctors and dtors require a particular syntax that uses the tag on the class. Thus, X::W() and X::~W() are ill-formed because W is not a tag. W::X() and W::~X() are well-formed (although I would not willingly write code that looked like that) because W is a typename and X is the tag name associated with it. If all you have is a typedef name, you can't call the class destructor explicitly. But you hardly ever need to call a destructor explicitly. If you need to do so, it is usually because you are doing things that involve the class implementation, in which case you have the actual class definition available. You don't often need a constructor's name. Since the typedef is a type name for the class, that is usually all you need. (You can use the typedef name in a constructor initializer list.) Examples: W w1(arg1, arg2); // construct W object class U : public W { U(); }; // use as base class U::U() : W() { } // initialize base class