[/ 
  (C) Copyright Edward Diener 2011,2012,2014
  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE_1_0.txt or copy at
  http://www.boost.org/LICENSE_1_0.txt).
]

[section:tti_detail_has_member_function Introspecting member function]

The TTI macro [macroref BOOST_TTI_HAS_MEMBER_FUNCTION] introspects
a member function of a class.

BOOST_TTI_HAS_MEMBER_FUNCTION takes a single
parameter which is the name of an inner member function whose existence
the programmer wants to check. The macro generates a metafunction
called 'has_member_function_'name_of_inner_member_function'. 

The metafunction can be invoked in two different ways.

The first way of invoking the metafunction is by passing it the enclosing 
type to introspect and a signature for the member function as a series of 
separate template arguments. The signature for the member function consists 
of the template arguments of a return type, of optional parameter types in 
the form of a boost::mpl forward sequence of types, and of an optional Boost 
FunctionTypes tag type. A typical boost::mpl forward sequence of types is 
a boost::mpl::vector<>.

The optional Boost FunctionTypes tag type may be used to specify 
cv-qualification. This means you can add 'const', 'volatile', or both by 
specifying an appropriate tag type. An alternate to using the tag type 
is to specify the enclosing type as 'const', 'volatile', or both.
As an example if you specify the tag type as 
'boost::function_types::const_qualified' or if you specify the enclosing
type as 'const T', the member function which you are introspecting 
must be a const function.

The second way of invoking the metafunction is by passing it a single 
parameter, which is a pointer to member function. This type has the form of:

 Return_Type ( Enclosing_Type::* ) ( Parameter_Types ) cv_qualifier(s)
 
where the Parameter_Types may be empty, or a comma-separated 
list of parameter types if there are more than one parameter type.
The cv-qualifier may be 'const', 'volatile', or 'const volatile'.

The metafunction returns a single type called 'type', which is a 
boost::mpl::bool_. As a convenience the metafunction 
returns the value of this type directly as a compile time bool constant 
called 'value'. This 'value' is true or false depending on whether the inner 
member function, of the specified signature, exists or not.

[heading Generating the metafunction]

You generate the metafunction by invoking the macro with the name 
of an inner member function:

  BOOST_TTI_HAS_MEMBER_FUNCTION(AMemberFunction)
  
generates a metafunction called 'has_member_function_AMemberFunction' in the current scope.

[heading Invoking the metafunction]

You invoke the metafunction by instantiating the template with an enclosing 
type to introspect and the signature of the member function as a series of template
parameters. Alternatively you can invoke the metafunction by passing it a single 
type which is a pointer to member function.

A return value called 'value' is a compile time bool constant.

  has_member_function_AMemberFunction
    <
    Enclosing_Type,
    MemberFunction_ReturnType,
    boost::mpl::vector<MemberFunction_ParameterTypes>, // optional, can be any mpl forward sequence
    boost::function_types::SomeTagType                 // optional, can be any FunctionTypes tag type
    >::value
    
  OR  
  
  has_member_function_AMemberFunction
    <
    MemberFunction_ReturnType (Enclosing_Type::*) (MemberFunction_ParameterTypes) optional_cv_qualification
    >::value
    
[heading Examples]

First we generate metafunctions for various inner member function names: 

 #include <boost/tti/has_member_function.hpp>
 
 BOOST_TTI_HAS_MEMBER_FUNCTION(function1)
 BOOST_TTI_HAS_MEMBER_FUNCTION(function2)
 BOOST_TTI_HAS_MEMBER_FUNCTION(function3)
 
Next let us create some user-defined types we want to introspect. 

 struct AClass 
   { 
   };
 struct Top
   {
   int function1();
   AClass function2(double,short *);
   };
 struct Top2
   {
   long function2(Top &,int,bool,short,float);
   Top * function3(long,int,AClass &);
   };
   
Finally we invoke our metafunction and return our value.
This all happens at compile time, and can be used by 
programmers doing compile time template metaprogramming.
  
We will show both forms in the following examples. 
Both forms are completely interchangeable as to the result
desired.

 has_member_function_function1<Top,int>::value; // true
 has_member_function_function1<Top,int,boost::mpl::vector<> >::value; // true
 has_member_function_function1<Top2,int>::value; // false
 
 has_member_function_function2<AClass (Top::*) (double,short *)>::value; // true
 has_member_function_function2<AClass (Top2::*) (double,short *)>::value; // false
 has_member_function_function2<long (Top2::*) (Top &,int,bool,short,float)>::value; // true
 
 has_member_function_function3<int (Top2::*) ()>::value; // false
 has_member_function_function3<Top2,Top *,boost::mpl::vector<long,int,AClass &> >::value; // true;
   
[heading Metafunction re-use]

The macro encodes only the name of the member function for which
we are searching and the fact that we are introspecting for a
member function within an enclosing type.

Because of this, once we create our metafunction for 
introspecting a member function by name, we can reuse the 
metafunction for introspecting any enclosing type, having any 
member function, for that name.

[endsect]
