11.2 Deduced Contexts

Ru-Brd

11.2 Deduced Contexts

Parameterized types that are considerably more complex than T can be matched to a given argument

type. Here are a few examples that are still fairly basic:

 template<typename T>  void f1(T*);  template<typename E, int N>  void f2(E(&)[N]);  template<typename T1, typename T2, typename T3>  void f3(T1 (T2::*)(T3*));  class S {    public:      void f(double*);  };  void g (int*** ppp)  {      bool b[42];      f1(ppp);  // deduces  T  to be  int**      f2(b);  // deduces  E  to be  bool  and  N  to be  42      f3(&S::f);  // deduces  T1 = void  ,  T2=S  , and  T3 = double  } 

Complex type declarations are built from more elementary constructs (pointer, reference, array, and function declarators; pointer-to-member declarators; template-ids; and so forth), and the matching process proceeds from the top-level construct and recurses through the composing elements. It is fair to say that most type declaration constructs can be matched in this way, and these are called deduced contexts . However, a few constructs are not deduced contexts:

  • Qualified type names . A type name like Q<T>::X will never be used to deduce a template parameter T , for example.

  • Nontype expressions that are not just a nontype parameter. A type name like S<I+1> will never be used to deduce I , for example. Neither will T be deduced by matching against a parameter of type int(&)[sizeof(S<T>)] .

These limitations should come as no surprise because the deduction would, in general, not be unique (or even finite), although qualified type names are sometimes easily overlooked. A nondeduced context does not automatically imply that the program is in error or even that the parameter being analyzed cannot participate in type deduction . To illustrate this, consider the following, more intricate example:

  // details/fppm.cpp  template <int N>  class X {    public:      typedef int I;      void f(int) {      }  };  template<int N>  void fppm(void (X<N>::*p)(X<N>::I));  int main()  {      fppm(&X<33>::f);  // fine:  N  deduced to be  33  } 

In the function template fppm() , the subconstruct X<N>::I is a nondeduced context. However, the member-class component X<N> of the pointer-to-member type is a deducible context, and when the parameter N , which is deduced from it, is plugged in the nondeduced context, a type compatible with that of the actual argument &X<33>::f is obtained. The deduction therefore succeeds on that argument-parameter pair.

Conversely, it is possible to deduce contradictions for a parameter type entirely built from deduced contexts. For example, assuming suitably declared class templates X and Y :

 template<typename T>  void f(X<Y<T>, Y<T> >);  void g()  {      f(X<Y<int>, Y<int> >());  // OK  f(X<Y<int>, Y<char> >());  // ERROR: deduction fails  } 

The problem with the second call to the function template f() is that the two arguments deduce different arguments for the parameter T , which is not valid. (In both cases, the function call argument is a temporary object obtained by calling the default constructor of the class template X .)

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