Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / tti / doc / tti_func_templates.qbk
1 [/ 
2   (C) Copyright Edward Diener 2011
3   Distributed under the Boost Software License, Version 1.0.
4   (See accompanying file LICENSE_1_0.txt or copy at
5   http://www.boost.org/LICENSE_1_0.txt).
6 ]
7
8 [section:tti_func_templates Introspecting Function Templates]
9
10 The one nested element which the TTI library does not introspect is 
11 function templates.
12
13 Function templates, like functions, can be member function templates or 
14 static member function templates. In this respect they are related to 
15 functions. Function templates represent a family of possible functions.
16 In this respect they are similar to class templates, which represent a 
17 family of possible class types.
18
19 The technique for introspecting class templates in the TTI library is taken 
20 from the implementation of the technique in the Boost MPL library. In the case
21 of `BOOST_TTI_HAS_TEMPLATE` it directly uses the Boost MPL library functionality 
22 while in the case of `BOOST_TTI_HAS_TEMPLATE_CHECK_PARAMS` it replicates much 
23 of the technique in the Boost MPL library. The technique depends directly on 
24 the fact that in C++ we can pass a template as a parameter to another template
25 using what is called a "template template" parameter type. 
26
27 One obvious thing about a template template parameter type is that it is a 
28 class template. For whatever historical or technical reasons, no one has ever
29 proposed that C++ have a way of passing a function template directly as a template 
30 parameter, perhaps to be called a "function template template" parameter type. 
31 I personally think this would be a good addition to C++ and would 
32 make the ability of passing a template as a parameter to another template 
33 more orthogonal, since both class templates and function templates would be supported. 
34 My efforts to discuss this on the major C++ newsgroups have 
35 met with arguments both against its practical usage and the justification
36 that one can pass a function template to another template nested in a non-template 
37 class, which serves as a type. But of course we can do the same thing with class templates, 
38 which is in fact what Boost MPL does to pass templates as metadata, yet we still have 
39 template template parameters as class templates.
40
41 Nonetheless the fact that we can pass class templates as a template parameter but not
42 function templates as a template parameter is the major factor why there is no really good
43 method for introspecting function templates at compile time.
44
45 [heading Instantiating a nested function template]
46
47 There is, however, an alternate but less certain way of introspecting a function template.
48 I will endeavor to explain why this way is not currently included in the TTI library, 
49 but first I will explain what it is.
50
51 It is possible to check whether some particular [*instantiation] of a nested function 
52 template exists at compile-time without generating a compiler error. Although checking if 
53 some particular instantiation of a nested function template exists at compile-time does
54 not prove that the nested function template itself does or does not exist, 
55 since the instantiation itself may be incorrect and fail even when the nested function 
56 template exists, it provides a partial, if flawed, means of checking.
57
58 The code to do this for member function templates looks like this 
59 ( similar code also exists for static member function templates ):
60
61   template
62     <
63     class C,
64     class T
65     > 
66   struct TestFunctionTemplate
67     {
68     typedef char Bad;
69     struct Good { char x[2]; };
70     template<T> struct helper;
71     template<class U> static Good check(helper<&U::template SomeFuncTemplateName<int,long,double> > *);
72     template<class U> static Bad check(...);
73     static const bool value=sizeof(check<C>(0))==sizeof(Good);
74     };
75     
76 where 'SomeFuncTemplateName' is the name of the nested function template, 
77 followed by some parameters to instantiate it. The 'class C' is the type of 
78 the enclosing class and the 'class T' is the type of the instantiated member 
79 function template as a member function.
80
81 As an example if we had:
82
83   struct AType 
84     {
85     template<class X,class Y,class Z> double SomeFuncTemplateName(X,Y *,Z &) { return 0.0; }
86     };
87     
88 then instantiating the above template with:
89
90   TestFunctionTemplate
91     <
92     AType,
93     double (AType::*)(int,long *,double &)
94     >
95     
96 would provide a compile-time boolean value which would tell us whether the 
97 nested member function template exists for the particular instantiation 
98 provided above. Furthermore, through the use of a macro, the TTI library
99 could provide the means for specifying the name of the nested member function
100 template ('SomeFuncTemplateName' above) and its set of instantiated 
101 parameters ('int,long,double' above) for generating the template.
102
103 So why does not the TTI library not provide at least this much functionality for 
104 introspecting member function templates, even if it represents a partially flawed
105 way of doing so ? 
106
107 The reason is stunningly disappointing. Although the above code is perfectly correct C++ 
108 code ( 'clang' works correctly ), two of the major C++ compilers, in all of their different 
109 releases, can not handle the above code correctly. Both gcc ( g++ ) and Visual C++ incorrectly 
110 choose the wrong 'check' function even when the correct 'check' function applies ( Comeau C++
111 also fails but I am less concerned about that compiler since it is not used nearly as much as 
112 the other two ). All my attempts at alternatives to the above code have also failed. The problems 
113 with both compilers, in this regard, can be seen more easily with this snippet:
114
115   struct AType
116    {
117    template<class AA> void SomeFuncTemplate() { }
118    };
119    
120   template<class T>
121   struct Test
122    {
123    template<T> struct helper;
124    template<class U> static void check(helper<&U::template SomeFuncTemplate<int> > *) { }
125    };
126
127   int main()
128     {
129     Test< void (AType::*)() >::check<AType>(0);
130     return 0;
131     }
132     
133 Both compilers report compile errors with this perfectly correct code,
134
135 gcc: 
136
137   error: no matching function for call to 'Test<void (AType::*)()>::check(int)'
138
139 and msvc:
140
141   error C2770: invalid explicit template argument(s) for 'void Test<T>::check(Test<T>::helper<&U::SomeFuncTemplate<int>> *)'
142
143 There is a workaround for these compiler problems, which is to hardcode the name
144 of the enclosing class, via a macro, in the generated template rather than pass it as a 
145 template type. In that case both compilers can handle both the member function code and 
146 the code snippet above correctly. In essence, when the line:
147
148    template<class U> static void check(helper<&U::template SomeFuncTemplate<int> > *) { }
149    
150 gets replaced by:
151
152    template<class U> static void check(helper<&AType::template SomeFuncTemplate<int> > *) { }
153
154 both gcc and Visual C++ work correctly. The same goes for the 'check' line in the 
155 'TestFunctionTemplate' above.
156
157 But the workaround destroys one of the basic tenets of the TTI library, which is that 
158 the enclosing class be passed as a template parameter, especially as the enclosing class 
159 need not actually exist ( see `BOOST_TTI_MEMBER_TYPE` and the previous discussion of 'Nested Types' ), 
160 without producing a compiler error. So I have decided not to implement even this methodology to 
161 introspect nested function templates in the TTI library.
162
163 [endsect]