
Tobias Schwinger <tschwinger@neoscientists.org> writes:
Hi Dave,
David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> 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
Subtypes? I think you mean argument, optional class target, and return types. These are not (necessarily) "subtypes!" That word has a very specific -- and different -- meaning in computer science.
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?
It may be helpful somewhere, but "kind" is absolutely and utterly unnecessary for understanding the section I've rewritten here. Introducing it into these sentences just complicate them. A type supported by this library is completely described by its argument types, return type, class target (if the type is a member pointer), and the following properties: - decoration (none,pointer,reference,member pointer) - variadicity - cv-qualification of member function pointers - calling convention You really don't intend to represent cv-qualification of member function pointers as simply the cv-qualification attached to the class type?
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...
I have no clue what you mean.
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).
Okay, I understand. That said, the way you are classifying these things is going to cause confusion. There is no distinction between the types of static member functions and the types of free functions. There is only a distinction in how they are declared; once you are dealing with their types, they are the same thing. The name "free_or_static" carries the implication that you have precise (non-wildcard) tags "free" and "static". In my opinion, you should use the terms "member" and "nonmember." A pointer to a static member function is not a member pointer in the C++ type system; that's why my suggested terminology works. So "free_or_static" should be "nonmember."
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/
"(possibly decorated)" adds nothing. You have already made it clear that function types can be decorated -- or if you haven't, you can't just throw the term in here in parentheses and expect anyone to understand what you mean.
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.
Wha??? I can't tell what that means either.
This does not directly give us a use case
I don't understand what you mean by that either.
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_*.
Why does the user care what happens under the covers?
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.
Why make this so complicated? Just say that properties for which no value is specified acquire a default value, and show an example!
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.
That point may be interesting to you, but AFAICT it doesn't help a user in any way.
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.
I don't understand what you're saying there either.
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
I figured as much.
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!!!
Ah sorry, no I was just in a hurry. Make the final sentence of the paragraph: The specialization of tag used below indicates that the resulting function type should be a pointer to a variadic function.
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.
Okay.
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 >
That's why I said "not otherwise represented." I believe the statement is true.
So X and Y have different meanings but it won't matter unless they are used to (explicitly or implicitly) form another compound tag.
That may be a further interesting point to make, but I believe you should cover the topic of doubly-compound tags in a separate section, if at all.
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
Oh, wait. This use of "unspecified" is very bad, because it conflicts with the very specific way the C++ standard (and many Boost libraries as a result) use the word. The calling convention of the result isn't unspecified -- that would mean "it will be something whose properties we might describe but we're not going to tell you exactly what it is." In this case the calling convention is very much being specified to be the default! For this purpose, the proper name is "default_call."
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,
Allow what?
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.
I don't know what you're referring to.
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.
Yes, the behavior should be documented, but the way you are describing it exposes implementation details and complicates understanding. If you just say that "any properties of the first argument that are not overridden by the second argument will be properties of the result" then you don't need to introduce new jargon for "implicit tag combination." -- Dave Abrahams Boost Consulting www.boost-consulting.com