
Hi, after lots of re-thinking and fixing several flaws my sketch-pad update seems final. It includes an attempt to rewrite the tags section of the documentation for the proposed tag handling. I tried my best to make it clearly understandable and hope no flwas crept in so it works for you. The updated interface seems quite smooth to me, now. And even the names feel satisfactory (and after replacing that 'pof' placeholder used in the previous post). Thanks again to Jonathan Turkanis for his suggestion to split the tags -- it really makes things a lot easier to use (and hopefully explain) and even brings more flexiblity to the library. The term "function type" (which conflicts with the standard) in the current documentation will be worked around with some: "optionally decorated function [type]" or just "type" where the context allows it. Any proof-reading is very very much welcome! Regards, Tobias TODO List: ----------
Documentation: - revise text in respect to the reviewer's notes - inline examples, add short examples of typical use cases - add a tutorial - port to BoostBook on the fly
Library: - wrap interface in namespace, shorten/improve identifier names - cv-qualify class types of member function pointer - add unary (TypeTraits-style) traits for classification for most common cases - decorate member function pointers' class type in 'signature' with a reference by default - allow a placeholder name in calling conventions configuration to allow "explicitly empty" cc-attributation to address MSVC's '__thiscall' which cannot be specified explicity. - tag becomes the second (template-) parameter for tag-based metafunctions - improve tag logic by allowing combination of orthogonal aspects - simplify 'signature' by hiding most type members
- extend portability and test-sute, add V2 Jamfiles on the fly Synopsis (draft): -----------------
(lazy notation, all are class templates)
(brackets denote optional parts, single slashes denote variations)
// Classification is_function_pointer is_function_reference is_member_function_pointer_
is_function_<Type,QueryTag = undecorated> // previously: is_function_type kind_of<T> // returns tag of arbitrary type
// Decomposition arity // number of parameters of the function parameter[_c] // get a single parameter type class_of // class type of member function pointers (undecorated)
// (but cv-qualified)
parameters // MPL sequence of paramters signature<T, ClassDecoration = add_reference<_> > // Seq. of all types
effective_parameter[s/_c] // includes "this reference" (hard-wired)
// except for the sequence: ^
// Synthesis function_type<Signature_or_Seq_or_T // (*1) ,Tag = unspecified,ClassDecoration = add_reference<_> >
tag[n]<Tag_or_Signature // combined tag (*2) ,Tag1 [[= nil_t], Tag2 = [[nil_t], ...]] > represents<Tag_Or_Signature,QueryTag> // predicate to query a tag
(*1) function_type< signature<T> > replaces typename function_type_signature<T>::representee
(*2) tag< signature<T> > replaces typename function_type_signature<T>::kind
Tag types: ---------- The kinds of a type to be synthesised and complex classification queries are described by *tags types*. A tag encapsulates one or more aspects of the kind of type (see the reference section below for examples). Tags which only encapsulate a single aspect are called *aspect tags* in the following text. These can be used to query, whether a type's kind reflects this aspect: is_function_type< T, pointer > is_function_type< T, variadic > Aspects can be *abstract* : In this case several non-abstract possibilities of the same aspect are matched for querying: is_function_type< T, unbound > is equivalent to: mpl::or_< is_function_type< T, undecorated> , is_function_type< T, pointer> , is_function_type< T, reference> > When an aspect tag is used to specify the kind of type to be synthesized, only a single aspect is specified explicitly: function_type< mpl::single_view<void>, variadic >::type is void(...) function_type< void(), pointer >::type is void(*)() Abstract tag aspects are concretized to a default (see refernce below) when used for type synthesis: function_type<void(my_class::*)(), unbound>::type is void() When a tag is taken from a type, the resulting tag explicitly describes all aspects and none of them has abstract state: kind_of< void() > describes all aspects: undecorated, non-variadic, ... When classifying or synthesising types there are situations where it is neccessary to describe more than one aspect. Therefore tags can be combined. E.g. for synthesising a both variadic and pointer-decorated function: function_type< mpl::vector<int,int>, tag<pointer,variadic> >::type In classification context all aspects in the query tag must match: is_function_type< void(...), tag<unbound,variadic> >::value == true is_function_type< void(my_class::*)(...), tag<unbound,variadic> >::value == false When the 'tag' metafunction is used to combine tags, which describe different possibiltiies of the same aspects, the right hand side tag's aspect is used -- it *overrides* the aspect: tag<unbound,reference>'s decoration aspect is 'reference' tag<reference,undecorated>'s decoration aspect is 'undecorated' tag<unbound,reference,unbound>'s decoration aspect is 'unbound' Tag combination occurs either explicitly by using the 'tag' metafunction or implicitly when using 'function_type' with an optionally decorated function type or a specialization of 'signature' as its first template argument: function_type<void __cdecl(my_class::*)(),tag<undecorated,unspecified_call> > overrides the decoration and calling convention aspect of the 'void __cdecl(my_class*)()'s kind and thus returns 'void(my_class&)'. Aspect tag reference: --------------------- // Decoration aspect unspecified_decoration (*) (default) unbound (*) (matches the next three) undecorated pointer reference member_pointer (*) abstract - same as 'undecorated' when used for synthesis // Variadic aspect unspecified_variadic (*) (default) non_variadic variadic (*) abstract - same as 'non_variadic' when used for synthesis // Const aspect unspecified_constness (*) (default) const_ non_const (*) abstract - same qualfication as the class type when used for synthesis // Volatile aspect unspecified_volatility (*) (default) volatile_ non_volatile (*) abstract - same qualfication as the class type when used for synthesis // Calling convention aspect unspecified_call (*) (default) cdecl, stdcall, etc. (depends on configuration) (*) abstract - uses the default calling convention when used for synthesis