|
Boost : |
From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2005-07-01 12:54:29
Hi Dave,
David Abrahams wrote:
> Tobias Schwinger <tschwinger_at_[hidden]> writes:
>
>
> Let's try this again:
Thanks for your rewrite. I hope it gives us a starting point to finally straighten
this section, which seems quite tricky to document and I really can use any help
with it!
>
> Tag Types
> ----------
>
> The Function Types library uses *tag* types to represent or query one or
> more properties of a type, such as its variadicness, or whether it is
> a pointer.
>
The "kind" term from the previos version was meant to be defined in a more global
place. Like this:
A type supported by this library is completely described by its subtypes
and its kind. The kind collectively refers to the following information:
- decoration (none,pointer,reference,member pointer)
- variadicity
- cv-qualification of member function pointers
- the calling convention attribute
Actually it is very helpful - not only for this part. Maybe reintroduce it?
> Tags that represent the values of a single property are called
> *property tags*. These tags can be used to determine whether one
> property of the type has a particular value.
>
> is_function< T, variadic >
> is_function< T, pointer > // same as is_function_pointer<T>
>
> To match against several values of a property at once, you can use
> wildcard property tags:
"Wildcard" requires the context of classification to fit perfectly...
>
> is_function< T, free_or_static >
>
> // the tag 'free_or_static' captures two values of the decoration
> // property and makes the above code equivalent to:
>
> mpl::or_< is_function_type< T, undecorated>
> , is_function_type< T, pointer >
> , is_function_type< T, reference > >
>
> [?? This example doesn't make any sense to me; what do "undecorated,"
> "pointer," and "reference" have to do with whether a function is free
> or static?? If you really meant what you wrote, you had better
> explain -- at length!]
The very first sentence descibing the library in a whole introduces it (this has
not been posted yet). I'm not sure it is sufficient, though:
Overview
This library provides functionality to classify, decompose and synthesize
function types and other compound types directly decorating a function type
with a pointer, reference or member pointer.
So the idea behind the decoration property is this:
Given a function type F
F is undecorated \
F* is pointer decorated - free or static decoration ("wildcard")
F& is reference decorated /
C::*F is member-pointer-decorated
The reference shows this grouping, too. Unfortunately the "[/ FIXME: add link to
reference ]" at the point where the "aspect tags" are introduced got lost (because
I copied from the browser instead of my .qbk master file).
>
> Every property has a fully-general wildcard tag that can be used to indicate
> that /any/ value of the property should be matched. The tag's name is the
> same as that of the property, but with the prefix "unspecfied_".
>
> is_function< T, unspecified_decoration >::value
> // true for any type T that the library can handle
>
> [You need to say more clearly what "can handle" means. IMO the
> comment should really be expressed as the last sentence of the
> foregoing paragraph]
s/type the library can handle/(possibly decorated) function type/
>
>
>>Each abstract variation of an aspect has a non-abstract semantic
>>equivalence
>
>
> Wha??? I don't know how to translate that into something simpler,
> because I can't tell what it means!
>
It means that wildcards in fact are abstract ;-) and undergo a process of
"automatic concretization" in the context of type synthesis.
This does not directly give us a use case but is essential to understaning the
logic because it allows us to write:
function_type< mpl::vector<int,int>, pointer >::type
What happens here is: all properties other than the decoration property default to
unspecified_*.
These are "concretized" (in this context -- we need a concrete description for
creating a type) to produce a pointer to a non-variadic function of the default
calling convention.
Because of this "concretization", the same tag expressions work for both
classification and synthesis:
is_function<F,pointer>::value
Here ^^^ we ignore anything except the decoration property.
>
>>when used in the context of type synthesis (as defined
>>in the reference section).
>>
>> function_type<void(X::*)(), free_or_static>::type
>>
>> // is equivalent to:
>>
>> function_type<void(X::*)(), undecorated>::type
>
>
> And the example doesn't help me tell what it means, mostly because of
> my confusion above, probably.
>
As I said: it does not directly give a use case. So the "examples" are in fact
"demonstrations of behaviour" fundamental to the logic.
>
>>A tag created from a type completely describes all aspects of the type's kind. The
>>aspect variations in the tag are never abstract.
>>
>> signature< void() >
>> // describes all aspects: undecorated, non-variadic, ...
>
>
> A signature tag is a compound tag that precisely describes all of
> a specific type's properties, so it does not act as a wildcard.
>
> signature< void() >
> // describes all aspects: undecorated, non-variadic, ...
>
> [This example fails to illustrate your main point, which is that it
> doesn't act as a wildcard. That said, I'm not sure it's an important
> point to make -- it should be obvious! Anyway, if you use this
> section it should come after compound property tags are introduced below]
Agreed. I wasn't to happy about its placement either.
By the way:
signature<F>
// is model of: Tag & Front-/Back Extensible/Random Access MPL Sequence
>
>
>>When classifying and especially when synthesising types, there are situations in
>>which it is neccessary to describe more than one aspect. Therefore tags can be
>>combined using the tag metafunction.
>>
>> function_type< mpl::vector<int,int>, tag<pointer,variadic> >::type
>> // is int(*)(int...)
>
>
> [That "tag" template is not obviously a metafunction from its usage.
> I believe calling it that here (even if it really is one) is
> confusing. ]
OK. In fact I plan to document a Tag concept.
>
> A compound property tag describes a combination of possible values
> of different properties. The tag class template can be used to
> create a specific compound property tag. The specialization of tag
> used below matches all pointers to variadic functions, and the type
> vector further restricts the type matched to int(*)(int,...).
>
Hmm... I'm having difficulties combining this ^^ text with this VV example.
> function_type< mpl::vector<int,int>, tag<pointer,variadic> >::type
^^ this creates a function pointer, not a tag
The example was not sufficiently documented, I guess. Sorry!!!
>
>
>>In the context of classification all aspects represented by the
>>query tag must match:
>
>
>
> A compound property tag matches a type only when all of its
> component properties match:
>
It's not restricted to matching types. It's also possible to match other tags.
That's why I used the words I did. However, inserting "or another tag" does fix
it, I believe.
>
>> is_function_type< void(...), tag<free_or_static,variadic> >::value
>> // is true
>>
>> is_function_type< void(X::*)(...), tag<free_or_static,variadic> >::value
>> // is false
>>
>>Except for tag combination, each aspect that is not represented by a tag is
>>similar to the abstract variation represented by the tag named "unspecified_" plus
>>that aspect's name. This is why these tags do not have to be specified in many
>>contexts.
>
>
> [I don't know what "except for tag combination" is supposed to mean
> above, so I left it out below, but if it's important, you need to
> describe what _does_ happen when you use the fully-general wildcard in
> a "tag combination" (whatever that is)]
"Tag combination" was supposed to mean: "tag<T1,T2>".
What does happen is what happens for all properties described in the next paragraph.
>
> The fully-general wildcard tag for any property not otherwise
> represented can be added to a tag specialization without changing
> its meaning.
>
It's not entirely true (and what I was trying to say), because:
typedef tag< variadic, unspecified_decoration > X;
typedef variadic Y;
tag< pointer /* <-- gets overridden */ , X >
tag< pointer /* <-- does not get overridden */ , Y >
So X and Y have different meanings but it won't matter unless they are used to
(explicitly or implicitly) form another compound tag.
> [Now that I read it I guess I don't know whether I am even saying what
> you were trying to say here. And I don't know what use the 2nd
> sentence (which needs an antecedent for "this") is without an example]
>
>
>>When there are tags representing different variations of the same aspect in tag's
>>template argument list, the last variation is used; others are ignored.
>
>
> When several tags for the same property appear in the argument
> list, only the last one is used; others are ignored.
>
> [I assume we are still on the topic of the "tag" class template here,
> so "the argument list" is sufficient. I wonder if there's a rationale
> for this behavior, as opposed to making it a compile-time error?]
Oh yes. Try these:
// a remove constness (of the pointee) from a member function pointer type T
function_type<T, non_const >::type
or
// create a (possibly decorated) function type's variadic version
function_type<T, variadic >::type
or
// Member function pointer -> function with default calling convention
function_type<T, tag<undecorated,unspecified_call> >::type
Here the properties of the original types are overridden in an implicit tag
combination with the tag representing the type.
Well, we /could/ only allow it in this very context, however, it maybe makes
things more complicated to explain (see below) and involves more template
instantiations - so I'm not sure it's really worth it.
>
>
>> tag<free_or_static,reference>
>> // decoration aspect is 'reference'
>>
>> tag<reference,undecorated>
>> // decoration aspect is 'undecorated'
>>
>> tag<undecorated,reference,unspecified_decoration>
>> // decoration aspect is 'unspecified_decoration'
>>
>> tag<undecorated,variadic,pointer>
>> // two aspects are set: pointer decoration and variadic
>>
>>Tag combination occurs either explicitly by using the tag metafunction or
>>implicitly. Implicit tag combination takes place when using function_type with a
>>tag or (possibly decorated) function type as its first template
>>argument.
>
>
> Tags can be combined either explicitly, by using the tag
> metafunction, or implicitly. Implicit tag combination takes place
> when function_type is used with a tag or function type as its first
> template argument. In the example below, any properties of the
> first argument to function_type not overridden by those in the tag
> specialization are turned into a tag and implicitly combined with
> the tag specialization to produce a new function type.
>
> [personally I don't believe it's important for users to know that
> implicit tag combination happens here, and I think saying so just
> complicates matters. It would be just as useful to say that "any
> properties represented in the tag specialization override those of the
> first argument to produce a new function type," and leave it at that.]
No?
function_type< my_mpl_sequence, pointer > // no implicit tag combination
VVVVV
function_type< my_function , pointer > // implicit tag combination
function_type< signature<F> , pointer > // implicit tag combination
^^^^^
I believe it is _very_ important to document this behaviour.
>
>
>> function_type<void __cdecl(X::*)(),tag<undecorated,unspecified_call> >
>> // ::type member is 'void(my_class&)'
>> // the decoration and calling convention aspect are overridden
>
>
Thanks,
Tobias
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk