13.8 The typeof Operator

Ru-Brd

13.8 The typeof Operator

When writing templates, it is often useful to be able to express the type of a template-dependent expression. Perhaps the poster child of this situation is the declaration of an arithmetic operator for a numeric array template in which the element types of the operands are mixed. The following example should make this clear:

 template <typename T1, typename T2>  Array<  ???  > operator+ (Array<T1> const& x, Array<T2> const& y); 

Presumably, this operator is to produce an array of elements that are the result of adding corresponding elements in the arrays x and y . The type of a resulting element is thus the type of x[0]+y[0] . Unfortunately, C++ does not offer a reliable way to express this type in terms of T1 and T2 .

Some compilers provide the typeof operator as an extension that addresses this issue. It is reminiscent of the sizeof operator in that it can take an expression and produce a compile-time entity from it, but in this case the compile-time entity can act as the name of a type. In our previous example this allows us to write:

 template <typename T1, typename T2>  Array<typeof(T1()+T2())> operator+ (Array<T1> const& x,                                      Array<T2> const& y); 

This is nice, but not ideal. Indeed, it assumes that the given types can be default- initialized . We can work around this assumption by introducing a helper template as follows :

 template <typename T>  T makeT();  // no definition needed  template <typename T1, typename T2>  Array<typeof(makeT<T1>()+makeT<T2>())>    operator+ (Array<T1> const& x,               Array<T2> const& y); 

We really would prefer to use x and y in the typeof argument, but we cannot do so because they have not been declared at the point of the typeof construct. A radical solution to this problem is to introduce an alternative function declaration syntax that places the return type after the parameter types:

  // operator function template:  template <typename T1, typename T2>  operator+ (Array<T1> const& x, Array<T2> const& y)    -> Array<typeof(x+y)>;  // regular function template:  template <typename T1, typename T2>  function exp(Array<T1> const& x, Array<T2> const& y)    -> Array<typeof(exp(x, y))> 

As the example illustrates, a new keyword (here, function ) is necessary to enable the new syntax for nonoperator functions (for operator functions, the operator keyword is sufficient to guide the parsing process).

Note that typeof must be a compile-time operator. In particular, typeof will not take into account covariant return types, as the following example shows:

 class Base {    public:      virtual Base clone();  };  class Derived : public Base {    public:      virtual Derived clone();  // covariant return type  };  void demo (Base* p, Base* q)  {     typeof(p->clone()) tmp = p->clone();  //  tmp  will always have type  Base   } 

Section 15.2.4 on page 271 shows how promotion traits are sometimes used to partially address the absence of a typeof operator.

Ru-Brd


C++ Templates
C++ Templates: The Complete Guide
ISBN: 0201734842
EAN: 2147483647
Year: 2002
Pages: 185

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net