Boost logo

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