
The official review period for the function types library is now over. Tobias is on vacation now, and the review manager is still catching up on the last set of posts, so there will be a short hiatus before a result is announced. If there are any last minute comments or "out of time" reviews then please do post them anyway - but be aware that you're unlikely to get a reply from Tobias until he's back from vacation! [My apologies to Tobias for not announcing the end of the review yesterday, I just ran out of time, sorry!] John.

This post is used as a reply-hook to bundle my summary.

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 - change library name to "Function Type" (singular) - 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

Tag types: ---------- The kinds of a type to be synthesised and complex classification queries are described by *tag* types. A tag encapsulates one or more aspects of the kind of type (see reference). 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 can be specified explicitly: function_type< mpl::single_view<void>, variadic >::type is void(...) function_type< void(), pointer >::type is void(*)() Abstract tag aspects are concretized (see refernce) 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 have 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 (some more detail is still missing, here): // - decoration aspect typedef /.../ unspecified_decoration; // (*) (default) typedef /.../ unbound; // (*) (matches the next three) typedef /.../ undecorated; typedef /.../ pointer; typedef /.../ reference; typedef /.../ member_pointer; // (*) abstract - same as 'undecorated' when used for synthesis // - variadic aspect typedef /.../ unspecified_variadic; // (*) (default) typedef /.../ non_variadic; typedef /.../ variadic; // (*) abstract - same as 'non_variadic' when used for synthesis // - const aspect typedef /.../ unspecified_constness; // (*) (default) typedef /.../ const_; typedef /.../ non_const; // (*) abstract - same qualfication as the class type when used for synthesis // - volatile aspect typedef /.../ unspecified_volatility; // (*) (default) typedef /.../ volatile_; typedef /.../ non_volatile; // (*) abstract - same qualfication as the class type when used for synthesis // Calling convention aspect typedef /.../ unspecified_call; // (*) (default) typedef /.../ cdecl, stdcall, etc. (depends on configuration) // (*) abstract - uses the default calling convention when used for synthesis

The kinds of a type to be synthesised and complex classification queries are described by *tag* types.
A tag encapsulates one or more aspects of the kind of type (see reference).
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:
I'm not sure that abstract is the right word here, I had to read right through this text a couple of time to understand what you're driving at here: more than one tag, which may be mutually exclusive in the type system. So maybe: "Aspects can also be *abstract*. An abstract tag is the union of one or more tags, which are normally mutually exclusive. They are used when querying a type, if you don't care which of a set of mutually exclusive options is present, for example: is_function_type<T, unbound>::value will be true if T is a function type, a reference to a function, or a pointer to a function." This is still not terribly good English mind you! I also don't like the use of "unbound" here, the name doesn't mean anything to me. I see later on you have "unspecified_decoration", is this the same meaning? If so I very much prefer the latter.
Abstract tag aspects are concretized (see refernce) when used for type synthesis:
I don't think "concretized" is actually a word, but I know what you mean ;-) Maybe someone has a better suggestion? This is definitely going in the right direction IMO. John.

John Maddock wrote:
The kinds of a type to be synthesised and complex classification queries are described by *tag* types.
A tag encapsulates one or more aspects of the kind of type (see reference).
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:
I'm not sure that abstract is the right word here, I had to read right through this text a couple of time to understand what you're driving at here: more than one tag, which may be mutually exclusive in the type system. So maybe:
Yeah. This did not feel exactly perfect, when writing it. This sentence doesn't fit too well into the text flow, either -- and "aspect" and "abstract" sound very similar which makes it even harder to understand, I guess.
"Aspects can also be *abstract*. An abstract tag is the union of one or more tags, which are normally mutually exclusive. They are used when querying a type, if you don't care which of a set of mutually exclusive options is present, for example:
is_function_type<T, unbound>::value
will be true if T is a function type, a reference to a function, or a pointer to a function."
This is still not terribly good English mind you!
When classifying types, it is often neccessary to match supersets of possibilities for one aspect: The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case). is_function< T, unspecified_decoration >::value is true for T being a function, function pointer, function reference and member function pointer type. Does this read better (it's still incomplete)? Can we call them "super aspects"?
I also don't like the use of "unbound" here, the name doesn't mean anything to me. I see later on you have "unspecified_decoration", is this the same meaning? If so I very much prefer the latter.
"unbound" wants to mean "freestanding_or_static" (which is a bit lengthy).
Abstract tag aspects are concretized (see refernce) when used for type synthesis:
I don't think "concretized" is actually a word, but I know what you mean ;-)
I tried to get around overloading the term "default" once another time... When super aspects are encountered during type synthesis, the behaviour is the same as for one of its specializations by definition (see reference).
Maybe someone has a better suggestion?
Still welcome, of course!
This is definitely going in the right direction IMO.
Thanks again, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
John Maddock wrote:
The kinds of a type to be synthesised and complex classification queries are described by *tag* types.
A tag encapsulates one or more aspects of the kind of type (see reference).
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:
"Aspects can also be *abstract*. An abstract tag is the union of one or more tags, which are normally mutually exclusive. They are used when querying a type, if you don't care which of a set of mutually exclusive options is present, for example:
is_function_type<T, unbound>::value
will be true if T is a function type, a reference to a function, or a pointer to a function."
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
is_function< T, unspecified_decoration >::value
is true for T being a function, function pointer, function reference and member function pointer type.
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name). For example, is_function< T, unspecified_decoration >::value is true when T is a function, function pointer, function reference, or member function pointer type.
Does this read better (it's still incomplete)? Can we call them "super aspects"?
Is it necessary to have a name for combinations of aspects?
I also don't like the use of "unbound" here, the name doesn't mean anything to me. I see later on you have "unspecified_decoration", is this the same meaning? If so I very much prefer the latter.
"unbound" wants to mean "freestanding_or_static" (which is a bit lengthy).
"unbound" seems reasonable, but it is not used in C++ circles, so it is a foreign term. How about "free_or_static?" it isn't as long and "free function" is a normal term.
Abstract tag aspects are concretized (see refernce) when used for type synthesis:
I don't think "concretized" is actually a word, but I know what you mean ;-)
s/concretized/made concrete/
I tried to get around overloading the term "default" once another time...
When super aspects are encountered during type synthesis, the behaviour is the same as for one of its specializations by definition (see reference).
That sentence is essentially meaningless to me. Do you mean something like the following? The effect is "as if" each of the aspects in the query set had been used separately and the results from each query had been logically OR'ed together. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
John Maddock wrote:
The kinds of a type to be synthesised and complex classification queries are described by *tag* types.
A tag encapsulates one or more aspects of the kind of type (see reference).
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:
"Aspects can also be *abstract*. An abstract tag is the union of one or more tags, which are normally mutually exclusive. They are used when querying a type, if you don't care which of a set of mutually exclusive options is present, for example:
is_function_type<T, unbound>::value
will be true if T is a function type, a reference to a function, or a pointer to a function."
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
is_function< T, unspecified_decoration >::value
is true for T being a function, function pointer, function reference and member function pointer type.
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
It reads nice. But needs semantical adjustment: It's not about matching "several aspects" (that's what the combination of aspect tags is for) but about matching several possibilities of the very same aspect, otherwise I'ld have to change the definitions of the terms. => s/several aspects/the possibilties of one aspect/ => => s/all possibilties/all of them/ (so "possibilties" does not repeat) Further tags don't really "handle" things -- they are just data. "Describe" (or alike) would be better in this context. In a whole: When classifying types, it is often necessary to match against several possibilities of one aspect. The most important case is to match all of them. In other words, to ignore that aspect. The tags named "unspecified_" plus the aspect name describe these cases. Still clear enough?
For example,
is_function< T, unspecified_decoration >::value
is true when T is a function, function pointer, function reference, or member function pointer type.
Does this read better (it's still incomplete)? Can we call them "super aspects"?
Is it necessary to have a name for combinations of aspects?
It's helpful (see below).
I also don't like the use of "unbound" here, the name doesn't mean anything to me. I see later on you have "unspecified_decoration", is this the same meaning? If so I very much prefer the latter.
"unbound" wants to mean "freestanding_or_static" (which is a bit lengthy).
"unbound" seems reasonable, but it is not used in C++ circles, so it is a foreign term. How about "free_or_static?" it isn't as long and "free function" is a normal term.
Agreed. => s/unbound/free_or_static/g
Abstract tag aspects are concretized (see refernce) when used for type synthesis:
I don't think "concretized" is actually a word, but I know what you mean ;-)
s/concretized/made concrete/
I tried to get around overloading the term "default" once another time...
When super aspects are encountered during type synthesis, the behaviour is the same as for one of its specializations by definition (see reference).
That sentence is essentially meaningless to me. Do you mean something like the following?
The effect is "as if" each of the aspects in the query set had been used separately and the results from each query had been logically OR'ed together.
No. It's about what happens when an abstract tag (or whatever we call it) is used to describe a type to be created: An abstract tag has a non-abstract semantical equivalence when used in the context of type synthesis (as annotated in the reference draft of the original post). I've currently no idea how to say this without the "abstract" term, though. Thank you for helping, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
It reads nice. But needs semantical adjustment:
It's not about matching "several aspects" (that's what the combination of aspect tags is for) but about matching several possibilities of the very same aspect, otherwise I'ld have to change the definitions of the terms.
=> s/several aspects/the possibilties of one aspect/ => => s/all possibilties/all of them/ (so "possibilties" does not repeat)
Further tags don't really "handle" things -- they are just data. "Describe" (or alike) would be better in this context.
s/handled by/handled by using/ [While we're on English usage, and just in case you have or might use it in the documentation, note that your use of "alike" above is not idiomatically correct (in the US anyway), and I'm not positive it is semantically correct. "Similar" works fine as does "the like."]
When classifying types, it is often necessary to match against several possibilities of one aspect. The most important case is to match all of them. In other words, to ignore that aspect. The tags named "unspecified_" plus the aspect name describe these cases.
Still clear enough?
Pretty close: When classifying types it is often necessary to match against several variations of one aspect. The most important case is to match any variation; that is, to ignore that aspect. The tags named "unspecified_" plus the aspect's name describe these cases.
For example,
is_function< T, unspecified_decoration >::value
is true when T is a function, function pointer, function reference, or member function pointer type.
Does this read better (it's still incomplete)? Can we call them "super aspects"?
Is it necessary to have a name for combinations of aspects?
It's helpful (see below). [snip]
When super aspects are encountered during type synthesis, the behaviour is the same as for one of its specializations by definition (see reference).
That sentence is essentially meaningless to me. Do you mean something like the following?
The effect is "as if" each of the aspects in the query set had been used separately and the results from each query had been logically OR'ed together.
No. It's about what happens when an abstract tag (or whatever we call it) is used to describe a type to be created:
An abstract tag has a non-abstract semantical equivalence when used in the context of type synthesis
s/semantical/semantic/ With that, it seems pretty good.
I've currently no idea how to say this without the "abstract" term, though.
I don't understand the subject well enough to offer any more help here, I'm afraid. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Further tags don't really "handle" things -- they are just data. "Describe" (or alike) would be better in this context.
s/handled by/handled by using/
[While we're on English usage, and just in case you have or might use it in the documentation, note that your use of "alike" above is not idiomatically correct (in the US anyway), and I'm not positive it is semantically correct. "Similar" works fine as does "the like."]
Oh thanks -- a good thing to know (never thought it's formal, but it seems it's not even informal ;-) ).
When classifying types, it is often necessary to match against several possibilities of one aspect. The most important case is to match all of them. In other words, to ignore that aspect. The tags named "unspecified_" plus the aspect name describe these cases.
Still clear enough?
Pretty close:
When classifying types it is often necessary to match against several variations of one aspect. The most important case is to match any variation; that is, to ignore that aspect. The tags named "unspecified_" plus the aspect's name describe these cases.
Nice! "Variation" seems way better than "possibility"...
No. It's about what happens when an abstract tag (or whatever we call it) is used to describe a type to be created:
An abstract tag has a non-abstract semantical equivalence when used in the context of type synthesis
s/semantical/semantic/
With that, it seems pretty good.
Interesting! My dictionary tells me both "semantical" and "semantic" exist and both are adjectives with the same translation... Is it lying? Or does it depend on the context which one to use?
I've currently no idea how to say this without the "abstract" term, though.
I don't understand the subject well enough to offer any more help here, I'm afraid.
Never mind! Seems straighter, already... Thanks, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
s/semantical/semantic/
Interesting! My dictionary tells me both "semantical" and "semantic" exist and both are adjectives with the same translation...
Is it lying? Or does it depend on the context which one to use?
I never knew "semantical" was an accepted variant of "semantic" until just now. I've no idea what their etymologies are, but I assume one predates the other. My guess is that "semantical" is the later to arrive and is more informal or colloquial. Either way, your usage was right! -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
s/semantical/semantic/
Interesting! My dictionary tells me both "semantical" and "semantic" exist and both are adjectives with the same translation...
Is it lying? Or does it depend on the context which one to use?
I never knew "semantical" was an accepted variant of "semantic" until just now. I've no idea what their etymologies are, but I assume one predates the other. My guess is that "semantical" is the later to arrive and is more informal or colloquial. Either way, your usage was right!
I like "semantic" better, because it's simpler. "Semantical" was my intuitive translation and I just tested it with an online dictionary to make sure it really is a word and didn't know there is an alternative before your post.

Tobias Schwinger <tschwinger@neoscientists.org> writes:
Interesting! My dictionary tells me both "semantical" and "semantic" exist and both are adjectives with the same translation...
Is it lying? Or does it depend on the context which one to use?
Doesn't matter. Despite what the dictionary says, nobody uses "semantical." -- Dave Abrahams Boost Consulting www.boost-consulting.com

Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
I can't understand either phrasing. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
I can't understand either phrasing.
With or without its context (five levels up the thread)?

Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
I can't understand either phrasing.
With or without its context (five levels up the thread)?
Without, I guess. But it's hard to imagine a context that makes it understandable. In particular, The most important case is to match all possibilities. In other words, to ignore that aspect. There is no singular thing for "that" to refer to here. Also, the text there beginning with "In other words," and ending with a period is not a complete sentence. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
I can't understand either phrasing.
With or without its context (five levels up the thread)?
Without, I guess. But it's hard to imagine a context that makes it understandable. In particular,
The most important case is to match all possibilities. In other words, to ignore that aspect.
There is no singular thing for "that" to refer to here.
True for the second version, for the first (and the latest, parallel to you post in this thread) there is "one aspect" in the preceding sentence. Is it too far away?
Also, the text there beginning with "In other words," and ending with a period is not a complete sentence.
Will it become a valid subordinate clause if we change the period before it to a dash? In a whole: When classifying types, it is often necessary to match against several possibilities of one aspect. The most important case is to match all of them -- in other words: to ignore that aspect. The tags named "unspecified_" plus the aspect name describe these cases. Does this work? Thanks, Tobias

Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
True for the second version, for the first (and the latest, parallel to you post in this thread) there is "one aspect" in the preceding sentence. Is it too far away?
Well, it appears visually to be in a separate paragraph, so yes. Now I think I begin to understand it, but it seems like the you could drop "which means in fact..." What does it add that will help the reader?
Also, the text there beginning with "In other words," and ending with a period is not a complete sentence.
Will it become a valid subordinate clause if we change the period before it to a dash?
In a whole:
When classifying types, it is often necessary to match against several possibilities of one aspect. The most important case is to match all of them -- in other words: to ignore that aspect. The tags named "unspecified_" plus the aspect name describe these cases.
Does this work?
Better. Does this documentation really define what a "possibility of an aspect" is? If not, you had better do so, or better yet, pick more understandable and evocative terminology. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
True for the second version, for the first (and the latest, parallel to you post in this thread) there is "one aspect" in the preceding sentence. Is it too far away?
Well, it appears visually to be in a separate paragraph, so yes.
Ah, good point! I'll remove the line break.
Also, the text there beginning with "In other words," and ending with a period is not a complete sentence.
Will it become a valid subordinate clause if we change the period before it to a dash?
In a whole:
When classifying types, it is often necessary to match against several possibilities of one aspect. The most important case is to match all of them -- in other words: to ignore that aspect. The tags named "unspecified_" plus the aspect name describe these cases.
Does this work?
Better. Does this documentation really define what a "possibility of an aspect" is? If not, you had better do so, or better yet, pick more understandable and evocative terminology.
I'll use the term "variation" instead of "possibility" (as just proposed by Rob Stewart): Tag types: ---------- ( changes: "variations of" inserted, corrected misplaced "(see reference)" ) The kinds of a type to be synthesised and complex classification queries are described by *tag* types. A tag encapsulates one or more aspects of the kind of type. Tags which only encapsulate variations of a single aspect are called *aspect tags* in the following text (see reference). ^^^ links to: Aspect tags: ------------ // - decoration aspect typedef /.../ unspecified_decoration; // (*) (default) typedef /.../ unbound; // (*) (matches the next three) typedef /.../ undecorated; typedef /.../ pointer; typedef /.../ reference; typedef /.../ member_pointer; // (*) abstract - same as 'undecorated' when used for synthesis // - variadic aspect typedef /.../ unspecified_variadic; // (*) (default) typedef /.../ non_variadic; typedef /.../ variadic; // (*) abstract - same as 'non_variadic' when used for synthesis ... Does it work?! Thanks, Tobias

Tobias Schwinger <tschwinger@neoscientists.org> writes:
I'll use the term "variation" instead of "possibility" (as just proposed by Rob Stewart):
Tag types: ----------
( changes: "variations of" inserted, corrected misplaced "(see reference)" )
The kinds of a type to be synthesised and complex classification queries are described by *tag* types.
A tag encapsulates one or more aspects of the kind of type.
Tags which only encapsulate variations of a single aspect are called *aspect tags* in the following text (see reference).
^^^ links to:
Lovely! "which" should be "that," though, at least by U.S. English rules" Normally, "which" should only follow a comma in a fragment that could be removed without altering the meaning of a sentence, as in "I felt lousy, which might have been good since I didn't want to go anyway." -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Wed, Jun 29, 2005 at 10:46:47AM -0400, David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
A tag encapsulates one or more aspects of the kind of type.
Tags which only encapsulate variations of a single aspect are called *aspect tags* in the following text (see reference).
^^^ links to:
Lovely! "which" should be "that," though, at least by U.S. English rules" Normally, "which" should only follow a comma in a fragment that could be removed without altering the meaning of a sentence, as in "I felt lousy, which might have been good since I didn't want to go anyway."
That seems wrong to me. A style-guide which requires that is being a bit picky IMHO. c.f. Chambers: http://www.chambersharrap.co.uk/chambers/chref/chref.py/main?title=21st&query=which Your rule seems only to apply to the 3rd definition, which is not the sense in which Tobias is using "which". jon

From: Jonathan Wakely <cow@compsoc.man.ac.uk>
On Wed, Jun 29, 2005 at 10:46:47AM -0400, David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
A tag encapsulates one or more aspects of the kind of type.
Tags which only encapsulate variations of a single aspect are called *aspect tags* in the following text (see reference).
^^^ links to:
Lovely! "which" should be "that," though, at least by U.S. English rules" Normally, "which" should only follow a comma in a fragment that could be removed without altering the meaning of a sentence, as in "I felt lousy, which might have been good since I didn't want to go anyway."
That seems wrong to me. A style-guide which requires that is being a bit picky IMHO.
c.f. Chambers: http://www.chambersharrap.co.uk/chambers/chref/chref.py/main?title=21st&query=which Your rule seems only to apply to the 3rd definition, which is not the sense in which Tobias is using "which".
Merriam Webster's Dictionary of English Usage, (c) 1994, pp894f, provides much discussion of the matter. It seems "that" predates "which," but fell into disrepute. It later reappeared and now enjoys some parity with "which." The conclusion of the long section is: If the discussion in many of the handbooks are complex and burdened with exceptions, the facts of usage are quite simple. Virginia McDavid's 1977 study shows that about 75 percent of the instances of "which" in edited prose introduce restrictive clauses; about 25 percent, nonrestrictive ones. We conclude that at the end of the 20th century, the usage of "which" and "that"--at least in prose--has pretty much settled down. You can use either "which" or "that" to introduce a restrictive clause--the grounds for your choice should be stylistic--and "which" to introduce a nonrestrictive clause. Thus, Tobias' use of "which" to introduce the restrive clause is fine. (Note that M-W didn't provide data indicating how often "which" is used versus "that" when introducing restrictive clauses. Thus, we cannot judge whether "that" is used more often than "which" to introduce restrictive clauses.) -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Jonathan Wakely <cow@compsoc.man.ac.uk> writes:
On Wed, Jun 29, 2005 at 10:46:47AM -0400, David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
A tag encapsulates one or more aspects of the kind of type.
Tags which only encapsulate variations of a single aspect are called *aspect tags* in the following text (see reference).
^^^ links to:
Lovely! "which" should be "that," though, at least by U.S. English ^^^^^^^^^^^^ rules" Normally, "which" should only follow a comma in a fragment that could be removed without altering the meaning of a sentence, as in "I felt lousy, which might have been good since I didn't want to go anyway."
That seems wrong to me. A style-guide which requires that is being a bit picky IMHO.
Tell that to my publisher.
c.f. Chambers: http://www.chambersharrap.co.uk/chambers/chref/chref.py/main?title=21st&query=which Your rule seems only to apply to the 3rd definition, which is not the sense in which Tobias is using "which".
British English has it's own, different, rules. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Thu, Jun 30, 2005 at 10:57:57PM -0400, David Abrahams wrote:
Jonathan Wakely <cow@compsoc.man.ac.uk> writes:
On Wed, Jun 29, 2005 at 10:46:47AM -0400, David Abrahams wrote:
Lovely! "which" should be "that," though, at least by U.S. English ^^^^^^^^^^^^ rules" Normally, "which" should only follow a comma in a fragment that could be removed without altering the meaning of a sentence, as in "I felt lousy, which might have been good since I didn't want to go anyway."
That seems wrong to me. A style-guide which requires that is being a bit picky IMHO.
Tell that to my publisher.
:-) fair enough
c.f. Chambers: http://www.chambersharrap.co.uk/chambers/chref/chref.py/main?title=21st&query=which Your rule seems only to apply to the 3rd definition, which is not the sense in which Tobias is using "which".
British English has it's own, different, rules.
Yes, that's true, although isn't Merriam-Webster American? Rob's quote supported my position. I'm not concerned either way, seems as though you guys are doing a fine job of re-working the docs without my pedantry (I was an English "language lawyer" long before I'd heard of C++ ;) jon

Jonathan Wakely <cow@compsoc.man.ac.uk> writes:
On Thu, Jun 30, 2005 at 10:57:57PM -0400, David Abrahams wrote:
Jonathan Wakely <cow@compsoc.man.ac.uk> writes:
On Wed, Jun 29, 2005 at 10:46:47AM -0400, David Abrahams wrote:
Lovely! "which" should be "that," though, at least by U.S. English ^^^^^^^^^^^^ rules" Normally, "which" should only follow a comma in a fragment that could be removed without altering the meaning of a sentence, as in "I felt lousy, which might have been good since I didn't want to go anyway."
That seems wrong to me. A style-guide which requires that is being a bit picky IMHO.
Tell that to my publisher.
:-) fair enough
c.f. Chambers: http://www.chambersharrap.co.uk/chambers/chref/chref.py/main?title=21st&query=which Your rule seems only to apply to the 3rd definition, which is not the sense in which Tobias is using "which".
British English has it's own, different, rules.
Yes, that's true, although isn't Merriam-Webster American? Rob's quote supported my position.
FWIW, my publisher's rule comes from The Chicago Manual of Style. http://www.press.uchicago.edu/Misc/Chicago/cmosfaq/cmosfaq.WhichvsThat.html And here you can read both sides of the argument, with the author landing squarely on the other side: http://itre.cis.upenn.edu/~myl/languagelog/archives/002124.html This guy obviously finds Merriam Webster convincing and other authorities, not. And this http://www.worldwidewords.org/articles/which.htm gives the "British perspective," which posits even more complicated rules. Personally, once I learned the rule nothing else sounds right to me. It's a curse, I suppose, because about 1/4 of the uses of "which" that I read jangle in my ear. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
I can't understand either phrasing.
With or without its context (five levels up the thread)?
Without, I guess. But it's hard to imagine a context that makes it understandable. In particular,
The most important case is to match all possibilities. In other words, to ignore that aspect.
There is no singular thing for "that" to refer to here.
The antecedent is missing. Sorry about that. s/that/an/
Also, the text there beginning with "In other words," and ending with a period is not a complete sentence.
Yeah, you're right, but I doubt that hindered your understanding. I'll take this up in response to Tobias' reply. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often neccessary to match supersets of possibilities for one aspect:
The most important case is to match all possibilities which means in fact to ignore that aspect (the names of the corresponding aspect tags are prefixed with "unspecified" for this case).
When classifying types, it is often necessary to match against any of several aspects. The most important case is to match all possibilities. In other words, to ignore that aspect. That case is handled by the tag named "unspecified_" plus the aspect name).
I can't understand either phrasing.
With or without its context (five levels up the thread)?
Without, I guess. But it's hard to imagine a context that makes it understandable. In particular,
The most important case is to match all possibilities. In other words, to ignore that aspect.
There is no singular thing for "that" to refer to here.
The antecedent is missing. Sorry about that. s/that/an/
That doesn't help. Then I have to ask "which aspect?" I can't connect "matching all possibilities" with "ignoring an aspect."
Also, the text there beginning with "In other words," and ending with a period is not a complete sentence.
Yeah, you're right, but I doubt that hindered your understanding.
When it's already confusing, a fragment like that one doesn't help.���q-- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
There is no singular thing for "that" to refer to here. =20
The antecedent is missing. Sorry about that. s/that/an/
That doesn't help. Then I have to ask "which aspect?" I can't connect "matching all possibilities" with "ignoring an aspect."
Tough crowd. 8^}
Also, the text there beginning with "In other words," and ending with a period is not a complete sentence.
Yeah, you're right, but I doubt that hindered your understanding. =20
When it's already confusing, a fragment like that one doesn't help.=8E=AC=
How's this: When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect and is only useful when also testing for other aspects. Ignoring an aspect means using an "unspecified_*" tag. For example, allowing a match for any decoration requires using the <tt>unspecified_decoration</tt> tag. I changed from "the most important" to "a common" because I suspect that's more appropriate. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
There is no singular thing for "that" to refer to here. =20
The antecedent is missing. Sorry about that. s/that/an/
That doesn't help. Then I have to ask "which aspect?" I can't connect "matching all possibilities" with "ignoring an aspect."
Tough crowd. 8^}
Also, the text there beginning with "In other words," and ending with a period is not a complete sentence.
Yeah, you're right, but I doubt that hindered your understanding. =20
When it's already confusing, a fragment like that one doesn't help.=8E=AC=
How's this:
When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect
No, way too twisty. You just lost me. Does the aspect mean "to allow...", or is it an "aspect that means (intends) to allow..." or is it "ignoring an aspect" that "means to allow...?" Try to resist the temptation to pack all the meaning into one sentence. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect
No, way too twisty. You just lost me. Does the aspect mean "to allow...", or is it an "aspect that means (intends) to allow..." or is it "ignoring an aspect" that "means to allow...?"
I don't see the problem. Please suggest an alternative that you don't find "way too twisty."
Try to resist the temptation to pack all the meaning into one sentence.
Neither quoted sentence seems long or complex. Perhaps there was something you snipped to which you were referring? Here's the full text of my suggestion: When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect and is only useful when also testing for other aspects. Ignoring an aspect means using an "unspecified_*" tag. For example, allowing a match for any decoration requires using the <tt>unspecified_decoration</tt> tag. Are you referring to the second sentence? I could split it at "and" forming two sentences: A common case is ignoring an aspect which means to allow a match for any variation of that aspect. That is only useful when also testing for other aspects. Is that what you wanted? I still find the original to be fine, but if you like the split version, I won't argue the point. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect
No, way too twisty. You just lost me. Does the aspect mean "to allow...", or is it an "aspect that means (intends) to allow..." or is it "ignoring an aspect" that "means to allow...?"
I don't see the problem. Please suggest an alternative that you don't find "way too twisty."
I don't have time to do that right now, and it's so ambiguous that I don't even know which of the 5 or 6 meanings I should represent.
Try to resist the temptation to pack all the meaning into one sentence.
Neither quoted sentence seems long or complex. Perhaps there was something you snipped to which you were referring?
No.
Here's the full text of my suggestion:
When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect and is only useful when also testing for other aspects. Ignoring an aspect means using an "unspecified_*" tag. For example, allowing a match for any decoration requires using the <tt>unspecified_decoration</tt> tag.
Are you referring to the second sentence?
Yes.
I could split it at "and" forming two sentences:
A common case is ignoring an aspect which means to allow a match for any variation of that aspect. That is only useful when also testing for other aspects.
Is that what you wanted?
No, all the same questions apply. It can be read several different ways: (ignoring an aspect) which means (to allow a match for any variation of that aspect.) or ignoring (an aspect (which means to allow a match for any variation of that aspect)) or ignoring (an aspect which means to allow a match)) for (any variation of that aspect) or... There really are many many more. And you don't really mean to say that "A common case" is doing the ignoring, do you? And there should be a comma before "which."
I still find the original to be fine,
Of course you do; you wrote it. It's still ambiguous in many ways. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect
No, way too twisty. You just lost me. Does the aspect mean "to allow...", or is it an "aspect that means (intends) to allow..." or is it "ignoring an aspect" that "means to allow...?"
I don't see the problem. Please suggest an alternative that you don't find "way too twisty."
I don't have time to do that right now, and it's so ambiguous that I don't even know which of the 5 or 6 meanings I should represent.
That doesn't leave us much opportunity to make progress.
Try to resist the temptation to pack all the meaning into one sentence.
Neither quoted sentence seems long or complex. Perhaps there was something you snipped to which you were referring?
No.
Since you said it was the second sentence (below), and you snipped part of it, then clearly it was to something you snipped that you were referring.
Here's the full text of my suggestion:
When classifying types, it is often necessary to test for any one of several variations of an aspect. A common case is ignoring an aspect which means to allow a match for any variation of that aspect and is only useful when also testing for other aspects. Ignoring an aspect means using an "unspecified_*" tag. For example, allowing a match for any decoration requires using the <tt>unspecified_decoration</tt> tag.
Are you referring to the second sentence?
Yes.
I could split it at "and" forming two sentences:
A common case is ignoring an aspect which means to allow a match for any variation of that aspect. That is only useful when also testing for other aspects.
Is that what you wanted?
No, all the same questions apply. It can be read several different ways:
(ignoring an aspect) which means (to allow a match for any variation of that aspect.)
or
ignoring (an aspect (which means to allow a match for any variation of that aspect))
or
ignoring (an aspect which means to allow a match)) for (any variation of that aspect)
or...
There really are many many more.
If you say so. I have to assume you're serious, but I really can't imagine how it is you think all of those (and more) variations are supported by the sentence in question.
And you don't really mean to say that "A common case" is doing the ignoring, do you?
Yes.
And there should be a comma before "which."
I'll grant that a comma there may be helpful, but it isn't necessary. Besides, I'm surprised to hear you call for a comma given your recent remark about how comma happy folks have become. The meaning is simple: - A common case is ignoring an aspect - Ignoring an aspect means to allow a match for any variation of that aspect Does adding the comma fix the confusion for you? A common case is ignoring an aspect, which means to allow a match for any variation of that aspect. That is only useful when also testing for other aspects.
I still find the original to be fine,
Of course you do; you wrote it. It's still ambiguous in many ways.
That's not true. I've noticed many problems with things I've written whether others point it out or not. When someone points out something, I give due consideration and try to evaluate what I've written as objectively as I can. I'm trying to understand your problem but I'm having a tough time doing so. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
And you don't really mean to say that "A common case" is doing the ignoring, do you?
Yes.
You must have misunderstood the question. I can't believe that the intended subject of the sentence is "the common case" and the verb phrase is "is ignoring" with direct object "an aspect." -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
And you don't really mean to say that "A common case" is doing the ignoring, do you?
Yes.
You must have misunderstood the question. I can't believe that the intended subject of the sentence is "the common case" and the verb phrase is "is ignoring" with direct object "an aspect."
Got it. I did misunderstand. The text should have indicated that a common case was when *you* wanted to ignore an aspect. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Since the discussion seems to be drifting apart, I tried to bundle it by applying its results. Please try to reply to make suggestions based on this version, so we don't waste too much energy on redundant work. Thanks, Tobias Tag types: ---------- The kinds of a type to be synthesised and complex classification queries are described by *tag* types. A tag encapsulates one or more aspects of the kind of type. Tags which only encapsulate variations of a single aspect are called *aspect tags* in the following text (see reference). Aspect tags can be used to query, whether a type's kind reflects this aspect: is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T> When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*. is_function< T, free_or_static > The free_or_static describes an abstract variation of the decoration aspect and makes the above code is equivalent to: mpl::or_< is_function_type< T, undecorated> , is_function_type< T, pointer> , is_function_type< T, reference> > An important use case for abstract variations is to match any variation of an aspect; that is, to ignore it in the context of type classification. Because of this, every aspect has at least one abstact variation, described by the (aspect) tag named "unspecified_" plus the aspect name. is_function< T, unspecified_decoration >::value // true for any type T the library can handle Each abstract variation of an aspect has a non-abstract semantical equivalence 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 When a tag is taken from a type, the resulting tag explicitly describes all aspects, none of them with an abstract variation: signature< void() > ANNOTATION: ^^^ will be a model of Tag (this is not yet documented) // describes all aspects: undecorated, non-variadic, ... When classifying and especially when 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<free_or_static,variadic> >::value // is true is_function_type< void(X::*)(...), tag<free_or_static,variadic> >::value // is false When the 'tag' metafunction is used to combine tags, which describe different variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect: tag<free_or_static,reference> // decoration aspect is 'reference' tag<reference,undecorated> // decoration aspect is 'undecorated' tag<undecorated,reference,undecorated> // decoration aspect is 'undecorated' Tag combination occurs either explicitly by using the 'tag' metafunction or implicitly when using 'function_type' with an optionally decorated function type or a tag as its first template argument: function_type<void __cdecl(X::*)(),tag<undecorated,unspecified_call> > // ::type member is 'void(my_class&)' // the decoration and calling convention aspect are overridden Aspect tag reference: --------------------- ANNOTATION: a proper explanation for "(default)" is still missing, please ignore it for now. // - decoration aspect typedef /.../ unspecified_decoration; // (*) (default) typedef /.../ unbound; // (*) (matches the next three) typedef /.../ undecorated; typedef /.../ pointer; typedef /.../ reference; typedef /.../ member_pointer; // (*) abstract - same as 'undecorated' when used for synthesis // - variadic aspect typedef /.../ unspecified_variadic; // (*) (default) typedef /.../ non_variadic; typedef /.../ variadic; // (*) abstract - same as 'non_variadic' when used for synthesis // - const aspect typedef /.../ unspecified_constness; // (*) (default) typedef /.../ const_; typedef /.../ non_const; // (*) abstract - same qualfication as the class type when used for synthesis // - volatile aspect typedef /.../ unspecified_volatility; // (*) (default) typedef /.../ volatile_; typedef /.../ non_volatile; // (*) abstract - same qualfication as the class type when used for synthesis // Calling convention aspect typedef /.../ unspecified_call; // (*) (default) typedef /.../ cdecl, stdcall, etc. (depends on configuration) // (*) abstract - uses the default calling convention when used for synthesis

From: Tobias Schwinger <tschwinger@neoscientists.org>
Tag types: ----------
The kinds of a type to be synthesised and complex classification queries are
I don't understand "the kinds of a type." Is this a reference to something discussed elsewhere? If so, reference that discussion. If not, clarify here.
described by *tag* types.
No paragraph break here.
A tag encapsulates one or more aspects of the kind of type.
s/kind/kinds/ to be consistent with the first sentence? (I still don't understand the phrase, though.)
Tags which only encapsulate variations of a single aspect are called
s/only encapsulate/represent the/ ?
*aspect tags* in the following text (see reference).
Strike "in the following text." You're creating the term for the library, not just the following text.
Aspect tags can be used to query, whether a type's kind reflects this aspect:
No comma. s/reflects/includes/ or s/reflects/is described by/ ?
is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T>
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
There are special tags that represent groups--or the union--of several variations of a single aspect. Shouldn't "abstract variations" be "abstract tags?" I think, like John suggested, that "composite tags" works better than "abstract tags." The special variation you use represents a grouping or union of variations, not a generalization of them.
is_function< T, free_or_static >
The free_or_static describes an abstract variation of the decoration aspect
^tag
and makes the above code is equivalent to:
s/is //
mpl::or_< is_function_type< T, undecorated> , is_function_type< T, pointer> , is_function_type< T, reference> >
An important use case for abstract variations is to match any variation of an aspect; that is, to ignore it in the context of type classification. Because of this, every aspect has at least one abstact variation, described by the
s/abstact variation/abstract tag/ (or "composite tag" ;0)
(aspect) tag named "unspecified_" plus the aspect name.
Instead of "unspecified_" how about "any_?" It is shorter and fits the prose. Whenever you discuss this, you refer to matching *any* variation.
is_function< T, unspecified_decoration >::value // true for any type T the library can handle
You said my version was incorrect because I suggested this query was only useful in combination with other queries. I don't see the point in asking whether a type fits any variation of an aspect while asking about no other aspects. In that case, you're asking about no aspects. The above suggests that one might have to choose an "any" aspect tag just to ask whether a type is a function type, but that just seems messy. So, what are the use cases for a query like the above in which nothing specific is queried?
Each abstract variation of an aspect has a non-abstract semantical equivalence
s/semantical/semantic/ I like the "non-abstract semantic equivalence" phrasing to explain the "concrete" usage of the tags.
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
That use of free_or_static seems just plain wrong. Why would you synthesize a type while giving a choice as to how it is decorated? Yes, you can document that free_or_static and undecorated are the same in this context, but it is confusing at best.
When a tag is taken from a type, the resulting tag explicitly describes all aspects, none of them with an abstract variation:
When querying for a tag describing a type, the result is a nonabstract tag that describes all aspects of the type. Yours was structured poorly, but more importantly, I didn't get the "taking" a tag from a type part. I'm sure mine doesn't capture the concept quite right, but hopefully it helps.
signature< void() > ANNOTATION: ^^^ will be a model of Tag (this is not yet documented) // describes all aspects: undecorated, non-variadic, ...
When classifying and especially when synthesising types, there are situations where it is neccessary to describe more than one aspect. Therefore tags can be
s/where/in which/ (situations aren't places)
combined.
combined in a single query using the tag metafunction.
E.g. for synthesising a both variadic and pointer-decorated function:
FWIW, I always find it appropriate to follow "for example" with a comma, so I consider it approprite to follow "e.g." with one.
function_type< mpl::vector<int,int>, tag<pointer,variadic> >::type
In classification context all aspects in the query tag must match:
s/context/contexts/
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
When the 'tag' metafunction is used to combine tags, which describe different
No comma.
variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect:
Try this instead: When using the tag metafunction to combine tags, it is possible to have different variations of the same aspect in the list. In that situation, the last (rightmost) variation is used; the others are ignored.
tag<free_or_static,reference> // decoration aspect is 'reference'
tag<reference,undecorated> // decoration aspect is 'undecorated'
tag<undecorated,reference,undecorated> // decoration aspect is 'undecorated'
Tag combination occurs either explicitly by using the 'tag' metafunction or implicitly when using 'function_type' with an optionally decorated function type or a tag as its first template argument:
Tag combination occurs either explicitly, by using the tag metafunction, or implicitly. Implicit tag combination occurs when using function_type with a tag or a (possibly decorated) function type as its first template argument.
function_type<void __cdecl(X::*)(),tag<undecorated,unspecified_call> > // ::type member is 'void(my_class&)' // the decoration and calling convention aspect are overridden
Aspect tag reference: ---------------------
ANNOTATION: a proper explanation for "(default)" is still missing, please ignore it for now.
// - decoration aspect typedef /.../ unspecified_decoration; // (*) (default)
any_decoration
typedef /.../ unbound; // (*) (matches the next three) typedef /.../ undecorated; typedef /.../ pointer; typedef /.../ reference; typedef /.../ member_pointer; // (*) abstract - same as 'undecorated' when used for synthesis
// - variadic aspect typedef /.../ unspecified_variadic; // (*) (default)
any_variadic
typedef /.../ non_variadic; typedef /.../ variadic; // (*) abstract - same as 'non_variadic' when used for synthesis
// - const aspect typedef /.../ unspecified_constness; // (*) (default)
any_constness
typedef /.../ const_; typedef /.../ non_const; // (*) abstract - same qualfication as the class type when used for synthesis
// - volatile aspect typedef /.../ unspecified_volatility; // (*) (default)
any_volatility
typedef /.../ volatile_; typedef /.../ non_volatile; // (*) abstract - same qualfication as the class type when used for synthesis
// Calling convention aspect typedef /.../ unspecified_call; // (*) (default)
any_call
typedef /.../ cdecl, stdcall, etc. (depends on configuration) // (*) abstract - uses the default calling convention when used for synthesis
-- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

That use of free_or_static seems just plain wrong. Why would you synthesize a type while giving a choice as to how it is decorated? Yes, you can document that free_or_static and undecorated are the same in this context, but it is confusing at best.
Since free functions and static [member] functions are the same type, should we just use "free_" as the prefix and drop "free_or_static_" ? I've no strong preference over this suggestion, just looking to avoid any confusion, John.

John Maddock wrote:
That use of free_or_static seems just plain wrong. Why would you synthesize a type while giving a choice as to how it is decorated? Yes, you can document that free_or_static and undecorated are the same in this context, but it is confusing at best.
Since free functions and static [member] functions are the same type, should we just use "free_" as the prefix and drop "free_or_static_" ?
To be precised, it isn't a prefix but a "full grown" identifier of an aspect tag ;-). Initially it was called "unbound". It was changed to "free_or_static" because it is more intuitive. But that "_or_" may cause confusion. So reverting to "unbound" would be another option...
I've no strong preference over this suggestion, just looking to avoid any confusion,
Yeah, me not either. Comments welcome! Regards, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
John Maddock wrote:
Since free functions and static [member] functions are the same type, should we just use "free_" as the prefix and drop "free_or_static_" ?
Initially it was called "unbound". It was changed to "free_or_static" because it is more intuitive. But that "_or_" may cause confusion.
So reverting to "unbound" would be another option...
In contradiction to my statement in another branch of this thread about not having multiple tags that are interchangeable, perhaps having both "free" and "static" would be helpful. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
John Maddock wrote:
Since free functions and static [member] functions are the same type, should we just use "free_" as the prefix and drop "free_or_static_" ?
Initially it was called "unbound". It was changed to "free_or_static" because it is more intuitive. But that "_or_" may cause confusion.
So reverting to "unbound" would be another option...
In contradiction to my statement in another branch of this thread about not having multiple tags that are interchangeable, perhaps having both "free" and "static" would be helpful.
And require another underscore suffix for static...

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
John Maddock wrote:
Since free functions and static [member] functions are the same type, should we just use "free_" as the prefix and drop "free_or_static_" ?
Initially it was called "unbound". It was changed to "free_or_static" because it is more intuitive. But that "_or_" may cause confusion.
So reverting to "unbound" would be another option...
In contradiction to my statement in another branch of this thread about not having multiple tags that are interchangeable, perhaps having both "free" and "static" would be helpful.
And require another underscore suffix for static...
Oh, right. There was an expressed desire to avoid the underscore. There's still the issue of which the library would use when querying a type, so I'll recant and return to my original goal: don't have duplicates. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Tag types: ----------
The kinds of a type to be synthesised and complex classification queries are
Here's a typo: it should be either "kinds of types" or "kind of a type".
I don't understand "the kinds of a type." Is this a reference to something discussed elsewhere?
"Elsewhere" is work in progress ;-). Here's a (maybe still bad) defintion: 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 ^^^^^^^^^^^ ANNOTATION: is this a word? Is it "variadicness" (sounds even stranger)? - cv-qualification of member function pointers - the calling convention attribute
described by *tag* types.
No paragraph break here.
OK - but why?
A tag encapsulates one or more aspects of the kind of type.
s/kind/kinds/ to be consistent with the first sentence? (I still don't understand the phrase, though.)
Caused by that ^$% typo above, I guess...
Tags which only encapsulate variations of a single aspect are called
s/only encapsulate/represent the/ ?
OK.
*aspect tags* in the following text (see reference).
Strike "in the following text." You're creating the term for the library, not just the following text.
OK.
Aspect tags can be used to query, whether a type's kind reflects this aspect:
No comma. s/reflects/includes/ or s/reflects/is described by/ ?
OK. How about "contains"?
is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T>
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
There are special tags that represent groups--or the union--of several variations of a single aspect.
Shouldn't "abstract variations" be "abstract tags?"
Don't think so: "aspects" and "variations" are semantics, the tags are their syntactical encapsulation.
I think, like John suggested, that "composite tags" works better than "abstract tags." The special variation you use represents a grouping or union of variations, not a generalization of them.
I'm afraid it /is/ in fact a generalization - see http://lists.boost.org/boost/2005/06/29472.php
is_function< T, free_or_static >
The free_or_static describes an abstract variation of the decoration aspect
^tag
and makes the above code is equivalent to:
s/is //
OK.
mpl::or_< is_function_type< T, undecorated> , is_function_type< T, pointer> , is_function_type< T, reference> >
An important use case for abstract variations is to match any variation of an aspect; that is, to ignore it in the context of type classification. Because of this, every aspect has at least one abstact variation, described by the
s/abstact variation/abstract tag/ (or "composite tag" ;0)
Noted. Not sure, yet.
(aspect) tag named "unspecified_" plus the aspect name.
Instead of "unspecified_" how about "any_?" It is shorter and fits the prose. Whenever you discuss this, you refer to matching *any* variation.
is_function< T, unspecified_decoration >::value // true for any type T the library can handle
Not sure here: function_type< mpl::single_view<int>, unspecified_call >::type == "give me a function type of the default calling convention (the one you get when you /don't specify/ it)" function_type< mpl::single_view<int>, any_call >::type == <just strange> I do like the shortening, though.
You said my version was incorrect because I suggested this query was only useful in combination with other queries. I don't see the point in asking whether a type fits any variation of an aspect while asking about no other aspects. In that case, you're asking about no aspects. The above suggests that one might have to choose an "any" aspect tag just to ask whether a type is a function type, but that just seems messy. So, what are the use cases for a query like the above in which nothing specific is queried?
If no second template argument is given, is_function asks for a "function type"; that is as defined by the standard, "undecorated": template<typename T, typename Tag = undecorated> struct is_function; Well, technically I could've used some "null tag" here, but it's more expressive to say what we want, isn't it? But this is not the only issue I had with that one of your versions (note btw. that the current version is also heavily inspired by a different one from you): typedef tag< some_query, unspecified_decoration > new_query; // widens a query but doesn't test anything
Each abstract variation of an aspect has a non-abstract semantical equivalence
s/semantical/semantic/
Whoops - this one crept in again...
I like the "non-abstract semantic equivalence" phrasing to explain the "concrete" usage of the tags.
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
That use of free_or_static seems just plain wrong. Why would you synthesize a type while giving a choice as to how it is decorated? Yes, you can document that free_or_static and undecorated are the same in this context, but it is confusing at best.
Imagine this case: function< typename function_type<MemFnPtr, free_or_static>::type > I think it does make sense to express 'free_or_static' (== "remove the member pointer, please") instead of 'undecorated', here. It's not about giving a choice to the library how things are done but giving a choice to the user to differently express things in different contexts. Further fail-safeness has some advantages. Remember btw. that the "_or_" in the name "free_or_static" does not reflect technical distinction but only exists in terminology. That's why I initially used "unbound" instead of "free_or_static". I know the "(default)" in the reference section is still very confusing. Please just ignore it, for now (it refers to the default of unset aspects *in a tag*, *not* to the template default arguments of the metafunctions).
When a tag is taken from a type, the resulting tag explicitly describes all aspects, none of them with an abstract variation:
When querying for a tag describing a type, the result is a nonabstract tag that describes all aspects of the type.
Yours was structured poorly, but more importantly, I didn't get the "taking" a tag from a type part. I'm sure mine doesn't capture the concept quite right, but hopefully it helps.
Inspired by "taking the address of an object" -- but you're right -- there is a serious flaw: the tag is not a property of the type. Either s/tag/kind/ or s/taking/creating/ fixes it. I prefer the former.
signature< void() > ANNOTATION: ^^^ will be a model of Tag (this is not yet documented) // describes all aspects: undecorated, non-variadic, ...
When classifying and especially when synthesising types, there are situations where it is neccessary to describe more than one aspect. Therefore tags can be
s/where/in which/ (situations aren't places)
OK.
combined.
combined in a single query using the tag metafunction.
OK. But s/in a single query// -- combination of tags does not imply querying.
E.g. for synthesising a both variadic and pointer-decorated function:
FWIW, I always find it appropriate to follow "for example" with a comma, so I consider it approprite to follow "e.g." with one.
OK. ... and probably spell it out. Looks nicer, I guess.
function_type< mpl::vector<int,int>, tag<pointer,variadic> >::type
In classification context all aspects in the query tag must match:
s/context/contexts/
OK.
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
When the 'tag' metafunction is used to combine tags, which describe different
No comma.
OK.
variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect:
Try this instead:
When using the tag metafunction to combine tags, it is possible to have different variations of the same aspect in the list. In that situation, the last (rightmost) variation
^^ "in the tags in the list" to be correct - note: syntax vs. semantics. After applying this correction I don't find it too appealing... What is wrong with the original in your opinion??
is used; the others are ignored.
tag<free_or_static,reference> // decoration aspect is 'reference'
tag<reference,undecorated> // decoration aspect is 'undecorated'
tag<undecorated,reference,undecorated> // decoration aspect is 'undecorated'
Tag combination occurs either explicitly by using the 'tag' metafunction or implicitly when using 'function_type' with an optionally decorated function type or a tag as its first template argument:
Tag combination occurs either explicitly, by using the tag metafunction, or implicitly. Implicit tag combination occurs when using function_type with a tag or a (possibly decorated) function type as its first template argument.
OK. Better. <snip reference> There's lots of valuable material in your post. Thank you, Tobias

Tobias Schwinger wrote:
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Tag types: ----------
The kinds of a type to be synthesised and complex classification queries are
Here's a typo: it should be either "kinds of types" or "kind of a type".
I don't understand "the kinds of a type." Is this a reference to something discussed elsewhere?
"Elsewhere" is work in progress ;-). Here's a (maybe still bad) defintion:
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 ^^^^^^^^^^^ ANNOTATION: is this a word? Is it "variadicness" (sounds even stranger)?
- cv-qualification of member function pointers - the calling convention attribute
described by *tag* types.
No paragraph break here.
OK - but why?
A tag encapsulates one or more aspects of the kind of type.
s/kind/kinds/ to be consistent with the first sentence? (I still don't understand the phrase, though.)
Caused by that ^$% typo above, I guess...
Tags which only encapsulate variations of a single aspect are called
s/only encapsulate/represent the/ ?
OK.
*aspect tags* in the following text (see reference).
Strike "in the following text." You're creating the term for the library, not just the following text.
OK.
Aspect tags can be used to query, whether a type's kind reflects this aspect:
No comma. s/reflects/includes/ or s/reflects/is described by/ ?
OK. How about "contains"?
Bad. But how about: Aspect tags can be used to query one particular aspect of the type's kind. ?
is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T>
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
There are special tags that represent groups--or the union--of several variations of a single aspect.
Shouldn't "abstract variations" be "abstract tags?"
Don't think so: "aspects" and "variations" are semantics, the tags are their syntactical encapsulation.
I think, like John suggested, that "composite tags" works better than "abstract tags." The special variation you use represents a grouping or union of variations, not a generalization of them.
I'm afraid it /is/ in fact a generalization - see http://lists.boost.org/boost/2005/06/29472.php
is_function< T, free_or_static >
The free_or_static describes an abstract variation of the decoration aspect
^tag
and makes the above code is equivalent to:
s/is //
OK.
mpl::or_< is_function_type< T, undecorated> , is_function_type< T, pointer> , is_function_type< T, reference> >
An important use case for abstract variations is to match any variation of an aspect; that is, to ignore it in the context of type classification. Because of this, every aspect has at least one abstact variation, described by the
s/abstact variation/abstract tag/ (or "composite tag" ;0)
Noted. Not sure, yet.
(aspect) tag named "unspecified_" plus the aspect name.
Instead of "unspecified_" how about "any_?" It is shorter and fits the prose. Whenever you discuss this, you refer to matching *any* variation.
is_function< T, unspecified_decoration >::value // true for any type T the library can handle
Not sure here:
function_type< mpl::single_view<int>, unspecified_call >::type
== "give me a function type of the default calling convention (the one you get when you /don't specify/ it)"
function_type< mpl::single_view<int>, any_call >::type
== <just strange>
I do like the shortening, though.
You said my version was incorrect because I suggested this query was only useful in combination with other queries. I don't see the point in asking whether a type fits any variation of an aspect while asking about no other aspects. In that case, you're asking about no aspects. The above suggests that one might have to choose an "any" aspect tag just to ask whether a type is a function type, but that just seems messy. So, what are the use cases for a query like the above in which nothing specific is queried?
If no second template argument is given, is_function asks for a "function type"; that is as defined by the standard, "undecorated":
template<typename T, typename Tag = undecorated> struct is_function;
Well, technically I could've used some "null tag" here, but it's more expressive to say what we want, isn't it?
But this is not the only issue I had with that one of your versions (note btw. that the current version is also heavily inspired by a different one from you):
typedef tag< some_query, unspecified_decoration > new_query; // widens a query but doesn't test anything
Each abstract variation of an aspect has a non-abstract semantical equivalence
s/semantical/semantic/
Whoops - this one crept in again...
I like the "non-abstract semantic equivalence" phrasing to explain the "concrete" usage of the tags.
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
That use of free_or_static seems just plain wrong. Why would you synthesize a type while giving a choice as to how it is decorated? Yes, you can document that free_or_static and undecorated are the same in this context, but it is confusing at best.
Imagine this case:
function< typename function_type<MemFnPtr, free_or_static>::type >
I think it does make sense to express 'free_or_static' (== "remove the member pointer, please") instead of 'undecorated', here.
It's not about giving a choice to the library how things are done but giving a choice to the user to differently express things in different contexts. Further fail-safeness has some advantages.
Remember btw. that the "_or_" in the name "free_or_static" does not reflect technical distinction but only exists in terminology. That's why I initially used "unbound" instead of "free_or_static".
I know the "(default)" in the reference section is still very confusing. Please just ignore it, for now (it refers to the default of unset aspects *in a tag*, *not* to the template default arguments of the metafunctions).
When a tag is taken from a type, the resulting tag explicitly describes all aspects, none of them with an abstract variation:
When querying for a tag describing a type, the result is a nonabstract tag that describes all aspects of the type.
Yours was structured poorly, but more importantly, I didn't get the "taking" a tag from a type part. I'm sure mine doesn't capture the concept quite right, but hopefully it helps.
Inspired by "taking the address of an object" -- but you're right -- there is a serious flaw: the tag is not a property of the type.
Either s/tag/kind/ or s/taking/creating/ fixes it. I prefer the former.
signature< void() > ANNOTATION: ^^^ will be a model of Tag (this is not yet documented) // describes all aspects: undecorated, non-variadic, ...
When classifying and especially when synthesising types, there are situations where it is neccessary to describe more than one aspect. Therefore tags can be
s/where/in which/ (situations aren't places)
OK.
combined.
combined in a single query using the tag metafunction.
OK. But s/in a single query// -- combination of tags does not imply querying.
E.g. for synthesising a both variadic and pointer-decorated function:
FWIW, I always find it appropriate to follow "for example" with a comma, so I consider it approprite to follow "e.g." with one.
OK. ... and probably spell it out. Looks nicer, I guess.
function_type< mpl::vector<int,int>, tag<pointer,variadic> >::type
In classification context all aspects in the query tag must match:
s/context/contexts/
OK.
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
When the 'tag' metafunction is used to combine tags, which describe different
No comma.
OK.
variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect:
Try this instead:
When using the tag metafunction to combine tags, it is possible to have different variations of the same aspect in the list. In that situation, the last (rightmost) variation
^^ "in the tags in the list" to be correct - note: syntax vs. semantics.
After applying this correction I don't find it too appealing...
What is wrong with the original in your opinion??
is used; the others are ignored.
tag<free_or_static,reference> // decoration aspect is 'reference'
tag<reference,undecorated> // decoration aspect is 'undecorated'
tag<undecorated,reference,undecorated> // decoration aspect is 'undecorated'
Tag combination occurs either explicitly by using the 'tag' metafunction or implicitly when using 'function_type' with an optionally decorated function type or a tag as its first template argument:
Tag combination occurs either explicitly, by using the tag metafunction, or implicitly. Implicit tag combination occurs when using function_type with a tag or a (possibly decorated) function type as its first template argument.
OK. Better.
<snip reference>
There's lots of valuable material in your post.
Thank you,
Tobias
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

From: Tobias Schwinger <tschwinger@neoscientists.org>
Aspect tags can be used to query one particular aspect of the type's kind.
Hmmm. I think we can do better. Try this: Aspect tags can be used to determine whether a type's kind includes a particular aspect. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Aspect tags can be used to query one particular aspect of the type's kind.
Hmmm. I think we can do better. Try this:
Aspect tags can be used to determine whether a type's kind includes a particular aspect.
The problem with this is: "wether the type's kind includes a particular aspect" is a tautology. The type's kind always includes all aspects there are -- we are asking for the variation of one particular aspect: Aspect tags can be used to determine whether one aspect of the type's kind matches a particular variation.

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Aspect tags can be used to query one particular aspect of the type's kind.
Hmmm. I think we can do better. Try this:
Aspect tags can be used to determine whether a type's kind includes a particular aspect.
The problem with this is: "wether the type's kind includes a particular aspect" is a tautology. The type's kind always includes all aspects there are -- we are
You understand the relationship among these things better than I. The sentence made sense to me because it was saying you use a tag to check for an aspect in a kind.
asking for the variation of one particular aspect:
I see what you mean now.
Aspect tags can be used to determine whether one aspect of the type's kind matches a particular variation.
Really? That doesn't make sense to me. I'm getting lost in the terminology now. An "aspect tag" sounds like something that would query for or specify--depending upon whether querying or synthesizing a type--an aspect. Your sentence says you use an "aspect tag" to look for a "variation." Yes, I know a variation is one of several in a set that describe the things that comprise an aspect (unless I really have things wrong now!), but it still gets confusing. OK, if I have the semantics correct, how does this sound? Aspect tags can be used to determine whether one variation--or a set of variations--of an aspect is included in a type's kind. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Tobias Schwinger wrote:
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
described by *tag* types.
No paragraph break here.
OK - but why?
The kinds of types to be synthesised and complex classification queries are described by *tag* types. A tag encapsulates one or more aspects of the kind of type. Tags that represent the variations of a single aspect are called *aspect tags*. or: The kinds of types to be synthesised and complex classification queries are described by *tag* types. A tag encapsulates one or more aspects of the kind of type. Tags that represent the variations of a single aspect are called *aspect tags*. ??

From: Tobias Schwinger <tschwinger@neoscientists.org>
The kinds of types to be synthesised and complex classification queries are described by *tag* types.
A tag encapsulates one or more aspects of the kind of type. Tags that represent the variations of a single aspect are called *aspect tags*.
or:
The kinds of types to be synthesised and complex classification queries are described by *tag* types. A tag encapsulates one or more aspects of the kind of type.
Tags that represent the variations of a single aspect are called *aspect tags*.
I wouldn't keep either break. Here's a variation of the sentences you wrote above (besides putting all three sentences in one paragraph). Complex classification queries and the kinds of types you can synthesize are described by *tag* types. A tag represents one or more aspects of a type's kind. Tags that represent the variations of a single aspect are called *aspect tags*. The first sentence, as you wrote it, was a bit awkward. While reading it, one first things the conjunction "and" combines "synthesized" and "complex." Reading on, one realizes that it is combining "kinds" and "queries." My rewrite should eliminate that problem. Also, I don't see the value in having two (or three) paragraphs for this text. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
The kinds of types to be synthesised and complex classification queries are described by *tag* types.
A tag encapsulates one or more aspects of the kind of type. Tags that represent the variations of a single aspect are called *aspect tags*.
or:
The kinds of types to be synthesised and complex classification queries are described by *tag* types. A tag encapsulates one or more aspects of the kind of type.
Tags that represent the variations of a single aspect are called *aspect tags*.
I wouldn't keep either break. Here's a variation of the sentences you wrote above (besides putting all three sentences in one paragraph).
Complex classification queries and the kinds of types you can synthesize are described by *tag* types. A tag represents one or more aspects of a type's kind. Tags that represent the variations of a single aspect are called *aspect tags*.
The first sentence, as you wrote it, was a bit awkward. While reading it, one first things the conjunction "and" combines "synthesized" and "complex." Reading on, one realizes that it is combining "kinds" and "queries." My rewrite should eliminate that problem.
This is a good point. I'm not entirely satisfied with your rewrite because more aggressive restructuring might even be better: The library uses *tag* types in order to represent or query a type's kind; a tag encapsulates one or more aspects of it. Tags that represent the variations of a single aspect are called *aspect tags*. Works?
Also, I don't see the value in having two (or three) paragraphs for this text.
Well, I'ld like to keep two paragraphs, one for each defintion. I find this kind of structuring helpful when reading documentation myself and I believe I'm not the only one. But I sometimes seem to overdo it when writing... Thanks, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
The library uses *tag* types in order to represent or query a type's kind; a tag encapsulates one or more aspects of it.
What's the antecedent of "it?" I can't figure out what you mean.
Tags that represent the variations of a single aspect are called *aspect tags*.
Well, I'ld like to keep two paragraphs, one for each defintion.
I find this kind of structuring helpful when reading documentation myself and I believe I'm not the only one. But I sometimes seem to overdo it when writing...
OK. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Tobias Schwinger wrote:
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T>
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
There are special tags that represent groups--or the union--of several variations of a single aspect.
Shouldn't "abstract variations" be "abstract tags?"
Don't think so: "aspects" and "variations" are semantics, the tags are their syntactical encapsulation.
But the term "variation" is used too often in this sentence. When classifying types it is often necessary to match against several variations of one aspect. There are special, *abstract* variations for that.

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
But the term "variation" is used too often in this sentence.
When classifying types it is often necessary to match against several variations of one aspect. There are special, *abstract* variations for that.
I'll grant that it is repetitious, but I don't care for your change. Here's another try: When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
But the term "variation" is used too often in this sentence.
When classifying types it is often necessary to match against several variations of one aspect. There are special, *abstract* variations for that.
I'll grant that it is repetitious, but I don't care for your change. Here's another try:
When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
Nice! Thanks!

Tobias Schwinger <tschwinger@neoscientists.org> writes:
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
But the term "variation" is used too often in this sentence.
When classifying types it is often necessary to match against several variations of one aspect. There are special, *abstract* variations for that.
I'll grant that it is repetitious, but I don't care for your change. Here's another try:
When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
Nice! Thanks!
Except that "this" needs an antecedent. -- Dave Abrahams Antecedent Nanny

From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
Rob Stewart wrote:
When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
Nice! Thanks!
Except that "this" needs an antecedent.
It has one: "to match." s/this/that/ would work better. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
Rob Stewart wrote:
When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
Nice! Thanks!
Except that "this" needs an antecedent.
It has one: "to match."
No, I mean, you can't just say "this;" you have to say "this <noun>." It's the <noun> that's missing. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
Rob Stewart wrote:
> When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
Nice! Thanks!
Except that "this" needs an antecedent.
It has one: "to match."
No, I mean, you can't just say "this;" you have to say "this <noun>." It's the <noun> that's missing.
Since when? I've never heard of that "rule." Can you cite a source for that? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
Rob Stewart wrote:
>> When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
Nice! Thanks!
Except that "this" needs an antecedent.
It has one: "to match."
No, I mean, you can't just say "this;" you have to say "this <noun>." It's the <noun> that's missing.
Since when? I've never heard of that "rule."
Your "sarcasm" is unwarranted. I learned this rule from Andrew Koenig, who said it was one of the surprising things he learned from his editors after writing his first book. The problem here is that the antecedent is unclear. What is "this?" "classifying types?" "matching against several variations?"
Can you cite a source for that?
http://wwwnew.towson.edu/ows/proref.htm has an example that exactly reflects your text, but you can google up numerous examples online that discuss the need for pronoun/antecedent agreement and clarity. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
I learned this rule from Andrew Koenig, who said it was one of the surprising things he learned from his editors after writing his first book.
I believe the root for this rule being surprising is that just saying "this" in informal, spoken language is often not big of a problem, because the receiver of a message can ask if things are unclear. However, a book or technical documentation communicates in a unidirectional way and asking for clarification is usually not that easy (as we usually don't drink tea with the authors of our favourite books or papers on a regular basis -- and even if, we'ld most likely know more interesting things to talk about and/or forget to ask ;-) ). I learned from Dave's numerous comments on this topic, that for these reasons it's imporant to be careful with 'this', 'that' and 'it' in written language. Strict-typedness (in some ways) buys us the same sort of clarity when programming (with the unfortunate difference, that compiling natural languages involves much more human work). And even without a formal requirement, adding an antecedent to every 'this' there is would still make a lot of sense (as those of you who know Perl will most likely "use strict" if the program gets longer than a handful of lines). Just my EUR -,02. Regards, Tobias

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
Rob Stewart wrote: >>> > When classifying types it is often necessary to match against > several variations of one aspect. Special, *abstract* > variations make this possible.
Nice! Thanks!
Except that "this" needs an antecedent.
It has one: "to match."
No, I mean, you can't just say "this;" you have to say "this <noun>." It's the <noun> that's missing.
Since when? I've never heard of that "rule."
Your "sarcasm" is unwarranted.
Actually, there was no sarcasm. I didn't want to call your statement a rule. I chose to put "rule" in quotes to identify your statement as something presented as a rule that quite likely was never established by a competent authority. In retrospect, I can see how that could come off wrong, so I apologize for the confusion.
I learned this rule from Andrew Koenig, who said it was one of the surprising things he learned from his editors after writing his first book.
The problem here is that the antecedent is unclear. What is "this?" "classifying types?" "matching against several variations?"
The antecedent could be "classifying types," but "to match" came later and is more specific. Thus, "to match" has a stronger association, which doesn't leave much room for the alternative to my ear. The pronoun could be replaced to remove all ambiguity, but that doesn't mean the sentence is _unclear_ as written.
Can you cite a source for that?
I've never before heard the "one, clear, unmistakable noun" discussion and was never taught that identification with antecedents was that strict. Certainly you should remove troublesome ambiguity, but must one always remove all possibility? The first example given, After putting the disk in the cabinet, Mabel sold it. doesn't strike me as necessarily confusing if read in context. Yes, it can be made clearer, but context normally fills in the gaps. I wouldn't change it unless it remains confusing when read as part of the paragraph to which it belongs.
has an example that exactly reflects your text, but you can google up numerous examples online that discuss the need for pronoun/antecedent agreement and clarity.
I find my text even less confusing than the disk/cabinet example. Unfortunately, English doesn't rigidly follow rules as much as grammarians would like. There are too many conflicting rules and regional practices to make it so. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes: > Rob Stewart wrote: >>>> >> When classifying types it is often necessary to match against >> several variations of one aspect. Special, *abstract* >> variations make this possible. > > Nice! Thanks!
Except that "this" needs an antecedent.
It has one: "to match."
No, I mean, you can't just say "this;" you have to say "this <noun>." It's the <noun> that's missing.
Since when? I've never heard of that "rule."
Your "sarcasm" is unwarranted.
Actually, there was no sarcasm. I didn't want to call your statement a rule. I chose to put "rule" in quotes to identify your statement as something presented as a rule that quite likely was never established by a competent authority.
Sorry, I should have said your "dismissiveness" is unwarranted. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Tag types: ----------
The kinds of a type to be synthesised and complex classification queries are
Here's a typo: it should be either "kinds of types" or "kind of a type".
Based upon your explanation below, it's the latter.
I don't understand "the kinds of a type." Is this a reference to something discussed elsewhere?
"Elsewhere" is work in progress ;-). Here's a (maybe still bad) defintion:
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 ^^^^^^^^^^^ ANNOTATION: is this a word? Is it "variadicness" (sounds even stranger)?
Well, I don't find "variadic" in my dictionary. My guess is that word was coined, so if you need a noun form of "variadic," you'd have to invent that, too. OTOH, you could rephrase: - whether the function is variadic
- cv-qualification of member function pointers - the calling convention attribute
Excellent. Now I understand. With a link from "kind of type" to this description, it should work fine.
described by *tag* types.
No paragraph break here.
OK - but why?
A paragraph is to be a cohesive set of sentences that posit and support a thesis. A proper paragraph is rarely a single sentence, though it certainly can be. In this case, the separated sentence simply amplifies on the information of those in the previous paragraph.
A tag encapsulates one or more aspects of the kind of type.
s/kind/kinds/ to be consistent with the first sentence? (I still don't understand the phrase, though.)
Caused by that ^$% typo above, I guess...
A tag encapsulates one or more aspects of a type's kind.
Aspect tags can be used to query, whether a type's kind reflects this aspect:
No comma. s/reflects/includes/ or s/reflects/is described by/ ?
OK. How about "contains"?
That's fine, but I think "includes" works a bit better--it doesn't conjure up container semantics to me.
is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T>
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
There are special tags that represent groups--or the union--of several variations of a single aspect.
Shouldn't "abstract variations" be "abstract tags?"
Don't think so: "aspects" and "variations" are semantics, the tags are their syntactical encapsulation.
Here you go again! I looked it up and was surprised to find that "syntactical" is a recognized variant of "syntactic." ;-) Nevertheless, I suggest "syntactic" rather than "syntactical." Anyway, as you say, "variations" are semantic, not syntactic elements. Thus, they aren't concrete by definition, right? The groups covered by a single tag are just that -- groups or combinations of tags. Trying to give that a name seems misguided unless it is a compound name like "variation set."
I think, like John suggested, that "composite tags" works better than "abstract tags." The special variation you use represents a grouping or union of variations, not a generalization of them.
I'm afraid it /is/ in fact a generalization - see http://lists.boost.org/boost/2005/06/29472.php
In that message, even you said you weren't convinced. I disagree with your analysis for the reasons stated. "Unspecified decoration" is not an abstraction or generalization of reference-decorated. It is a union of reference-decorated and the others.
(aspect) tag named "unspecified_" plus the aspect name.
Instead of "unspecified_" how about "any_?" It is shorter and fits the prose. Whenever you discuss this, you refer to matching *any* variation.
is_function< T, unspecified_decoration >::value // true for any type T the library can handle
Not sure here:
function_type< mpl::single_view<int>, unspecified_call >::type
== "give me a function type of the default calling convention (the one you get when you /don't specify/ it)"
function_type< mpl::single_view<int>, any_call >::type
== <just strange>
I do like the shortening, though.
Your version says, "Give me a function type of whatever calling convention you like, I don't care which one you choose," to me. So does mine. However, I raised that as an issue elsewhere anyway.
You said my version was incorrect because I suggested this query was only useful in combination with other queries. I don't see the point in asking whether a type fits any variation of an aspect while asking about no other aspects. In that case, you're asking about no aspects. The above suggests that one might have to choose an "any" aspect tag just to ask whether a type is a function type, but that just seems messy. So, what are the use cases for a query like the above in which nothing specific is queried?
If no second template argument is given, is_function asks for a "function type"; that is as defined by the standard, "undecorated":
template<typename T, typename Tag = undecorated> struct is_function;
Well, technically I could've used some "null tag" here, but it's more expressive to say what we want, isn't it?
That says you want to know if T is an undecorated function (whatever that is), not one with any of the recognized decorations. A "dont_care," "unused," or similar tag would say what you suggested it says now.
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
That use of free_or_static seems just plain wrong. Why would you synthesize a type while giving a choice as to how it is decorated? Yes, you can document that free_or_static and undecorated are the same in this context, but it is confusing at best.
Imagine this case:
function< typename function_type<MemFnPtr, free_or_static>::type >
I think it does make sense to express 'free_or_static' (== "remove the member pointer, please") instead of 'undecorated', here.
It's not about giving a choice to the library how things are done but giving a choice to the user to differently express things in different contexts. Further fail-safeness has some advantages.
Remember btw. that the "_or_" in the name "free_or_static" does not reflect technical distinction but only exists in terminology. That's why I initially used "unbound" instead of "free_or_static".
I was using that as an example because it was before me at the time. You're right that free functions and static member functions have the same function type, so this works as written. I was actually thinking about the examples I've seen in which you use the "unspecified" tags to pick up a default. I'm sorry I confused things. As to your point that "free_or_static" is better than "undecorated" in this case. I disagree. They are at least equivalent, and having one less tag to remember is better. After all, your library will have to choose one to report as part of a type's kind, so a client might not choose to use the one the library chooses, so that client will need to know both.
When a tag is taken from a type, the resulting tag explicitly describes all aspects, none of them with an abstract variation:
When querying for a tag describing a type, the result is a nonabstract tag that describes all aspects of the type.
Yours was structured poorly, but more importantly, I didn't get the "taking" a tag from a type part. I'm sure mine doesn't capture the concept quite right, but hopefully it helps.
Inspired by "taking the address of an object" -- but you're right -- there is a serious flaw: the tag is not a property of the type.
Either s/tag/kind/ or s/taking/creating/ fixes it. I prefer the former.
Only the former fits your text, and you didn't say whether you liked my version, so I'm not certain what you mean to be the result of the changes. Here's another stab that might be more accurate, and is certainly more succinct: The tags in a type's kind are explicit, not abstract.
E.g. for synthesising a both variadic and pointer-decorated function:
FWIW, I always find it appropriate to follow "for example" with a comma, so I consider it approprite to follow "e.g." with one.
OK. ... and probably spell it out. Looks nicer, I guess.
You can spell it out if you like, but "e.g." is ubiquitous.
variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect:
Try this instead:
When using the tag metafunction to combine tags, it is possible to have different variations of the same aspect in the list. In that situation, the last (rightmost) variation
^^ "in the tags in the list" to be correct - note: syntax vs. semantics.
After applying this correction I don't find it too appealing...
I agree. It's the wrong correction. See below.
What is wrong with the original in your opinion??
OK, here's your original:
When the 'tag' metafunction is used to combine tags, which describe different variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect:
These are some things I don't like about it: - passive voice ("is used to"); - doesn't spell out the case for this situation as mine attempts; - there is no "right hand side tag" if the list is broken across lines (I should have resisted the temptation to add "rightmost" to my version, but I didn't); - uses "overrides" versus "ignored" which introduces an unneeded term. Here's another try: When using the tag metafunction to combine tags, it is possible to have tags representing different variations of the same aspect in the same list. When that occurs, the last variation is used; the others are ignored. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Tag types: ----------
The kinds of a type to be synthesised and complex classification queries are
Here's a typo: it should be either "kinds of types" or "kind of a type".
Based upon your explanation below, it's the latter.
I don't understand "the kinds of a type." Is this a reference to something discussed elsewhere?
"Elsewhere" is work in progress ;-). Here's a (maybe still bad) defintion:
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 ^^^^^^^^^^^ ANNOTATION: is this a word? Is it "variadicness" (sounds even stranger)?
Well, I don't find "variadic" in my dictionary. My guess is that word was coined, so if you need a noun form of "variadic," you'd have to invent that, too. OTOH, you could rephrase:
"Variadic" seems to be a term specific to programming - here are the results of a Wikipedia search for it, for example: http://en.wikipedia.org/wiki/Variadic_function http://en.wikipedia.org/wiki/Variadic_macro http://en.wikipedia.org/wiki/C_programming_language http://en.wikipedia.org/wiki/Empty_product http://en.wikipedia.org/wiki/Name_mangling http://en.wikipedia.org/wiki/C_Plus_Plus
- whether the function is variadic
OK. This is better.
- cv-qualification of member function pointers - the calling convention attribute
Excellent. Now I understand. With a link from "kind of type" to this description, it should work fine.
described by *tag* types.
No paragraph break here.
OK - but why?
A paragraph is to be a cohesive set of sentences that posit and support a thesis. A proper paragraph is rarely a single sentence, though it certainly can be. In this case, the separated sentence simply amplifies on the information of those in the previous paragraph.
Makes sense.
A tag encapsulates one or more aspects of the kind of type.
s/kind/kinds/ to be consistent with the first sentence? (I still don't understand the phrase, though.)
Caused by that ^$% typo above, I guess...
A tag encapsulates one or more aspects of a type's kind.
Aspect tags can be used to query, whether a type's kind reflects this aspect:
No comma. s/reflects/includes/ or s/reflects/is described by/ ?
OK. How about "contains"?
That's fine, but I think "includes" works a bit better--it doesn't conjure up container semantics to me.
I changed it to a simpler form: Aspect tags can be used to query one particular aspect of a type's kind.
is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T>
When classifying types it is often necessary to match against several variations of one aspect. There are special variations which make this possible. These are called *abstract variations*.
There are special tags that represent groups--or the union--of several variations of a single aspect.
Shouldn't "abstract variations" be "abstract tags?"
Don't think so: "aspects" and "variations" are semantics, the tags are their syntactical encapsulation.
Here you go again! I looked it up and was surprised to find that "syntactical" is a recognized variant of "syntactic." ;-) Nevertheless, I suggest "syntactic" rather than "syntactical."
The dictionaries seem to list these versions to make things easier for people with a non-native English like me ;-).
Anyway, as you say, "variations" are semantic, not syntactic elements. Thus, they aren't concrete by definition, right? The
"Concrete" as opposed to "abstract" ? No, "variation" does not imply abstract or nonabstract.
groups covered by a single tag are just that -- groups or combinations of tags.
The tags in the reference are all "aspect tags": One for each "variation" of each "aspect" there is.
Trying to give that a name seems misguided
Why?
unless it is a compound name like "variation set."
I like this one: When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible. (taken from your recent post)
I think, like John suggested, that "composite tags" works better than "abstract tags." The special variation you use represents a grouping or union of variations, not a generalization of them.
I'm afraid it /is/ in fact a generalization - see http://lists.boost.org/boost/2005/06/29472.php
In that message, even you said you weren't convinced. I disagree
Yeah. That is not convinced that changing it is a good idea ;-).
with your analysis for the reasons stated. "Unspecified decoration" is not an abstraction or generalization of
It sure is! >>Considered apart from concrete existence: an abstract concept.<< It can be considered apart from concrete existence. And it is an abstract concept (within one aspect). It reads nicer using your "any" term, so let's use it here: "Reference-decoration" is also an "any-decoration". "Any-decoration" is a generalization of "reference-decoration". The aspects variations in a tag are not identical, just like a pointer type to an abstract base and a pointer type to a concrete class are not identical. Modeling each aspect with polymorphic classes, abstract variations would be abstract classes with the matches they bundle derived from them. For me it fits (almost) perfectly. However, I'm not pedantic about it -- and if it really causes confusion I should probably change it; I'ld very much like to retrace your lines of thinking before doing this (and I'm currently having some difficulties with this), though.
(aspect) tag named "unspecified_" plus the aspect name.
Instead of "unspecified_" how about "any_?" It is shorter and fits the prose. Whenever you discuss this, you refer to matching *any* variation.
is_function< T, unspecified_decoration >::value // true for any type T the library can handle
Not sure here:
function_type< mpl::single_view<int>, unspecified_call >::type
== "give me a function type of the default calling convention (the one you get when you /don't specify/ it)"
function_type< mpl::single_view<int>, any_call >::type
== <just strange>
I do like the shortening, though.
Your version says, "Give me a function type of whatever calling convention you like, I don't care which one you choose," to me.
No. In this context it means: don't tell the type system an explicit calling convention (the reference already states this). Same goes for cv-qualification, for example: "unspecified_constness" in synthesis context means: "I don't want to specifiy the constness *here* - use the qualfication of the class type to determine it" and *not*: "I don't care about the constness"
So does mine. However, I raised that as an issue elsewhere anyway.
Generalizing this the subtle difference: "Give me whatever this means in this context, I won't specify it here" instead of "I don't care"
You said my version was incorrect because I suggested this query was only useful in combination with other queries. I don't see the point in asking whether a type fits any variation of an aspect while asking about no other aspects. In that case, you're asking about no aspects. The above suggests that one might have to choose an "any" aspect tag just to ask whether a type is a function type, but that just seems messy. So, what are the use cases for a query like the above in which nothing specific is queried?
If no second template argument is given, is_function asks for a "function type"; that is as defined by the standard, "undecorated":
template<typename T, typename Tag = undecorated> struct is_function;
Well, technically I could've used some "null tag" here, but it's more expressive to say what we want, isn't it?
Sorry! ^^^^^ This is a very bad place for this sentence. I meant something different from what it reads like: I could have used a "null tag" _in_the_example_ (*not* for prototyping the metafunction).
That says you want to know if T is an undecorated function (whatever that is), not one with any of the recognized
The default arguments for the metafunctions are consistent with standard terms. is_function in particular is also consistent with Boost.TypeTraits.
decorations. A "dont_care," "unused," or similar tag would say what you suggested it says now.
To fully understand what I meant with the "null tag" sentence above I have to explain what "(default)" in the reference means: The semantics for unset aspects within a tag is equivalent to the one of the combination of all aspect tags marked with "(default)" (in the reference section) for these aspects, but with the exception that unset aspects cannot override set aspects in the context of tag combination.
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
That use of free_or_static seems just plain wrong. Why would you synthesize a type while giving a choice as to how it is decorated? Yes, you can document that free_or_static and undecorated are the same in this context, but it is confusing at best.
Imagine this case:
function< typename function_type<MemFnPtr, free_or_static>::type >
I think it does make sense to express 'free_or_static' (== "remove the member pointer, please") instead of 'undecorated', here.
It's not about giving a choice to the library how things are done but giving a choice to the user to differently express things in different contexts. Further fail-safeness has some advantages.
Remember btw. that the "_or_" in the name "free_or_static" does not reflect technical distinction but only exists in terminology. That's why I initially used "unbound" instead of "free_or_static".
I was using that as an example because it was before me at the time. You're right that free functions and static member functions have the same function type, so this works as written. I was actually thinking about the examples I've seen in which you use the "unspecified" tags to pick up a default. I'm sorry I confused things.
This is the same subtle issue as with the "unspecified" vs. "any" kind of thing, I guess...
As to your point that "free_or_static" is better than "undecorated" in this case. I disagree. They are at least equivalent, and having one less tag to remember is better. After
In practice the one is absolutely neccessary and the other one /very/ useful in the context of classification. For synthesis you can pick the one you like best. This is so, because there are no illegal tags in any context this way.
all, your library will have to choose one to report as part of a type's kind, so a client might not choose to use the one the library chooses, so that client will need to know both.
Considering classification is a much more common use case than synthesis, the client most likely needs to know both, anyway. However if it's only about synthesis - the client only has to know one. I'm not sure I understand what you mean, here. Can you perhaps try to explain it differently?
When a tag is taken from a type, the resulting tag explicitly describes all aspects, none of them with an abstract variation:
When querying for a tag describing a type, the result is a nonabstract tag that describes all aspects of the type.
Yours was structured poorly, but more importantly, I didn't get the "taking" a tag from a type part. I'm sure mine doesn't capture the concept quite right, but hopefully it helps.
Inspired by "taking the address of an object" -- but you're right -- there is a serious flaw: the tag is not a property of the type.
Either s/tag/kind/ or s/taking/creating/ fixes it. I prefer the former.
Only the former fits your text, and you didn't say whether you
;-) Noticed this, too. Haven't found the time to correct it, yet. Sorry, again.
liked my version, so I'm not certain what you mean to be the
Well I find "when querying for a tag describing a type" isn't exactly perfect. It is correct, but can easily lead to confusion because "querying" is used in a different context in other places of the text. I tried to transform it and ended up with rewriting the whole sentence: When a tag is created from a type, it completely describes all aspects of this type, so their variations are never abstract. Feels smooth to me. Does it work?
result of the changes. Here's another stab that might be more accurate, and is certainly more succinct:
The tags in a type's kind are explicit, not abstract.
^^^^ You meant aspects here, I guess. Except this, in itself it's quite nice. The problem is that I never was too happy with that "explicit" in the original and here the problem becomes even more obvious: it would need a full defintion.
E.g. for synthesising a both variadic and pointer-decorated function:
FWIW, I always find it appropriate to follow "for example" with a comma, so I consider it approprite to follow "e.g." with one.
OK. ... and probably spell it out. Looks nicer, I guess.
You can spell it out if you like, but "e.g." is ubiquitous.
I know it's alright -- "looks nicer" meant the typeface.
variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect:
Try this instead:
When using the tag metafunction to combine tags, it is possible to have different variations of the same aspect in the list. In that situation, the last (rightmost) variation
^^ "in the tags in the list" to be correct - note: syntax vs. semantics.
After applying this correction I don't find it too appealing...
I agree. It's the wrong correction. See below.
What is wrong with the original in your opinion??
OK, here's your original:
When the 'tag' metafunction is used to combine tags, which describe different variations of the same aspect, the right hand side tag's variation is used -- it *overrides* the aspect:
These are some things I don't like about it:
- passive voice ("is used to"); - doesn't spell out the case for this situation as mine attempts; - there is no "right hand side tag" if the list is broken across lines (I should have resisted the temptation to add "rightmost" to my version, but I didn't); - uses "overrides" versus "ignored" which introduces an unneeded term.
Here's another try:
When using the tag metafunction to combine tags, it is possible to have tags representing different variations of the same aspect in the same list. When that occurs, the last variation is used; the others are ignored.
It's OK, but not perfect yet, IMO: An adjustment is needed because of your previous s/combined/combined using the tag metafunction/-suggestion, so "tag metafunction" does not repeat. "Same list" reads a little strange to me. It can be fixed easily by using "template argument list of 'tag'" instead. We are talking about combination of tags anyway, so we might want to drop "when combining tags" as well. While we're at stripping it down, I don't think it's important to explicitly say that it is possible and that other aspects are ignored. How about: When there are tags representing different variations of the same aspect in the template argument list of 'tag', the last variation is used. Or maybe: s/is used/is dominant/ Btw. I don't think it is neccessary to spell this out in more detail. There should be another more complex example, though. Thanks, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Anyway, as you say, "variations" are semantic, not syntactic elements. Thus, they aren't concrete by definition, right? The
"Concrete" as opposed to "abstract" ?
Yes.
No, "variation" does not imply abstract or nonabstract.
Then it isn't semantic, right?
groups covered by a single tag are just that -- groups or combinations of tags.
The tags in the reference are all "aspect tags": One for each "variation" of each "aspect" there is.
Some represent groups of variations, right?
Trying to give that a name seems misguided
Why?
Because there are lots of new terms already, and it isn't always necessary to give everything a name to discuss it.
unless it is a compound name like "variation set."
I like this one:
When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
(taken from your recent post)
We're making progress, however slow.
I think, like John suggested, that "composite tags" works better than "abstract tags." The special variation you use represents a grouping or union of variations, not a generalization of them.
I'm afraid it /is/ in fact a generalization - see http://lists.boost.org/boost/2005/06/29472.php
In that message, even you said you weren't convinced. I disagree
Yeah. That is not convinced that changing it is a good idea ;-).
with your analysis for the reasons stated. "Unspecified decoration" is not an abstraction or generalization of
It sure is!
Well, I definitely disagree.
>>Considered apart from concrete existence: an abstract concept.<<
It can be considered apart from concrete existence. And it is an abstract concept (within one aspect).
The same can be said for all of the tags. None are concrete. They have no physical form.
It reads nicer using your "any" term, so let's use it here:
"Reference-decoration" is also an "any-decoration". "Any-decoration" is a generalization of "reference-decoration".
No. "Any-decoration" *includes* or *contains* "reference-decoration." It is not a generalization of it.
The aspects variations in a tag are not identical, just like a pointer type to an abstract base and a pointer type to a concrete class are not identical.
Modeling each aspect with polymorphic classes, abstract variations would be abstract classes with the matches they bundle derived from them.
For me it fits (almost) perfectly. However, I'm not pedantic about it -- and if it really causes confusion I should probably change it; I'ld very much like to retrace your lines of thinking before doing this (and I'm currently having some difficulties with this), though.
A base class pointer is not a more abstracted version of a derived class pointer. They are both pointers. What is more and less abstract are the classes. In the same way, one variation is not more abstract than another.
function_type< mpl::single_view<int>, unspecified_call >::type
== "give me a function type of the default calling convention (the one you get when you /don't specify/ it)"
function_type< mpl::single_view<int>, any_call >::type
== <just strange>
Your version says, "Give me a function type of whatever calling convention you like, I don't care which one you choose," to me.
No. In this context it means: don't tell the type system an explicit calling convention (the reference already states this).
I know that's what you claim it "says." I was telling you what it means to me when I read it.
Same goes for cv-qualification, for example:
"unspecified_constness"
in synthesis context means:
"I don't want to specifiy the constness *here* - use the qualfication of the class type to determine it"
and *not*:
"I don't care about the constness"
Then the constness is specified in that case. It is specified as that of the class type. Therefore, you need something other than "unspecified_constness" to express that.
Generalizing this the subtle difference:
"Give me whatever this means in this context, I won't specify it here"
instead of
"I don't care"
You can state that's what it means, but that's now what it means when one reads the code in ignorance. That is, consider the maintainer not familiar with the library. What does "unspecified" mean?
If no second template argument is given, is_function asks for a "function type"; that is as defined by the standard, "undecorated":
template<typename T, typename Tag = undecorated> struct is_function;
Well, technically I could've used some "null tag" here, but it's more expressive to say what we want, isn't it?
Sorry! ^^^^^ This is a very bad place for this sentence. I meant something different from what it reads like: I could have used a "null tag" _in_the_example_ (*not* for prototyping the metafunction).
That says you want to know if T is an undecorated function (whatever that is), not one with any of the recognized
The default arguments for the metafunctions are consistent with standard terms. is_function in particular is also consistent with Boost.TypeTraits.
If you say so. It still doesn't read well.
decorations. A "dont_care," "unused," or similar tag would say what you suggested it says now.
To fully understand what I meant with the "null tag" sentence above I have to explain what "(default)" in the reference means:
The semantics for unset aspects within a tag is equivalent to the one of the combination of all aspect tags marked with "(default)" (in the reference section) for these aspects, but with the exception that unset aspects cannot override set aspects in the context of tag combination.
There's another paragraph that needs work! Nevertheless, this has no bearing on readability, which is what I'm trying to address.
I was using that as an example because it was before me at the time. You're right that free functions and static member functions have the same function type, so this works as written. I was actually thinking about the examples I've seen in which you use the "unspecified" tags to pick up a default. I'm sorry I confused things.
This is the same subtle issue as with the "unspecified" vs. "any" kind of thing, I guess...
Yes.
As to your point that "free_or_static" is better than "undecorated" in this case. I disagree. They are at least equivalent, and having one less tag to remember is better. After
In practice the one is absolutely neccessary and the other one /very/ useful in the context of classification.
A good name may handle both with aplomb. If not, one might be only be applicable in one context, another in the other context.
For synthesis you can pick the one you like best. This is so, because there are no illegal tags in any context this way.
It still means there are multiple, interchangeable tags.
all, your library will have to choose one to report as part of a type's kind, so a client might not choose to use the one the library chooses, so that client will need to know both.
Considering classification is a much more common use case than synthesis, the client most likely needs to know both, anyway.
However if it's only about synthesis - the client only has to know one.
I'm not sure I understand what you mean, here. Can you perhaps try to explain it differently?
You say a client needs to know both anyway. That's only true if both are available. You say the client only needs to know one if doing synthesis. I don't think it's clear at this point how common it will be for clients to only do synthesis with the library, so making a case on that basis is a straw man at best.
I tried to transform it and ended up with rewriting the whole sentence:
When a tag is created from a type, it completely describes all aspects of this type, so their variations are never abstract.
Feels smooth to me. Does it work?
Not quite. Maybe this will do: A tag created from a type, it completely describes all of the aspects of the type. The aspect variations in the tag are never abstract. Note that I left "abstract" in only because you used it and aren't convinced to do otherwise. I don't think it is appropriate.
result of the changes. Here's another stab that might be more accurate, and is certainly more succinct:
The tags in a type's kind are explicit, not abstract.
^^^^ You meant aspects here, I guess. Except this, in itself it's quite nice.
The problem is that I never was too happy with that "explicit" in the original and here the problem becomes even more obvious: it would need a full defintion.
I'm not sure it should use "abstract" either. At this point, however, I'm lost as to what should or shouldn't be abstract. Perhaps it would be good to put everything together and provide larger, in context, extracts to consider in toto.
When using the tag metafunction to combine tags, it is possible to have tags representing different variations of the same aspect in the same list. When that occurs, the last variation is used; the others are ignored.
An adjustment is needed because of your previous s/combined/combined using the tag metafunction/-suggestion, so "tag metafunction" does not repeat.
I don't understand where the repetition is/will be.
"Same list" reads a little strange to me. It can be fixed easily by using "template argument list of 'tag'" instead.
I didn't like it a lot either. How about "tag's template argument list" instead and I think it will be fine.
We are talking about combination of tags anyway, so we might want to drop "when combining tags" as well.
Probably so.
While we're at stripping it down, I don't think it's important to explicitly say that it is possible and that other aspects are ignored.
How about:
When there are tags representing different variations of the same aspect in the template argument list of 'tag', the last variation is used.
Hmmm. I suppose you're right about the "it is possible" part, but I think the "ignored" part is helpful. When there are tags representing different variations of the same aspect in tag's template argument list, the last variation is used; the others are ignored.
Or maybe: s/is used/is dominant/
No.
Btw. I don't think it is neccessary to spell this out in more detail. There should be another more complex example, though.
OK. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Anyway, as you say, "variations" are semantic, not syntactic elements. Thus, they aren't concrete by definition, right? The
"Concrete" as opposed to "abstract" ?
Yes.
No, "variation" does not imply abstract or nonabstract.
Then it isn't semantic, right?
Can't see why it should imply this.
groups covered by a single tag are just that -- groups or combinations of tags.
The tags in the reference are all "aspect tags": One for each "variation" of each "aspect" there is.
Some represent groups of variations, right?
Well, not exactly. Some _match_ groups of (other) variations (in an appropriate context) *but* _represent_, well, /abstract/ concepts that include them. The "groups" you are talking about _are_ in fact _single_ variations of _single_ aspect tags.
Trying to give that a name seems misguided
Why?
Because there are lots of new terms already, and it isn't always necessary to give everything a name to discuss it.
"Aspect" and "variation" are proper English words, aren't they? Set into context by the preceding text.
unless it is a compound name like "variation set."
I like this one:
When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
(taken from your recent post)
We're making progress, however slow.
<snip> -> what's wrong with "abstract?" <-
No. "Any-decoration" *includes* or *contains* "reference-decoration." It is not a generalization of it.
It does not *include* or *contain* anything (see above). It represents an abstraction; because of this it _matches_ "reference-decoration". In different context there is an "automatic concretization" (for which to document I need the term).
The aspects variations in a tag are not identical, just like a pointer type to an abstract base and a pointer type to a concrete class are not identical.
Modeling each aspect with polymorphic classes, abstract variations would be abstract classes with the matches they bundle derived from them.
For me it fits (almost) perfectly. However, I'm not pedantic about it -- and if it really causes confusion I should probably change it; I'ld very much like to retrace your lines of thinking before doing this (and I'm currently having some difficulties with this), though.
A base class pointer is not a more abstracted version of a derived class pointer. They are both pointers. What is more and less abstract are the classes.
That's what I just said! Here's the analogy: Class type O--O Aspect variation Pointer/Class instance O--O Aspect encoded in a Tag Assuming special_aspect derived from (abstract base) aspect: // distinct at type level is_same<aspect*,special_aspect*>::value == false // "match" in the context of pointer assignment aspect* a1 = new special_aspect; // "automatic concretization" in a generic factory typedef typename mpl::eval_if< is_abstract<T> , concretize<T> , mpl::identity<T> >::type concrete_aspect; aspect* a2 = new aspect_type;
In the same way, one variation is not more abstract than another.
But they are (see above) ;-) -- this is why I don't want to call it any other way. <snip> -> "any" vs. "unspecified" <-
Generalizing this the subtle difference:
"Give me whatever this means in this context, I won't specify it here"
instead of
"I don't care"
You can state that's what it means, but that's now what it means when one reads the code in ignorance. That is, consider the maintainer not familiar with the library. What does "unspecified" mean?
He's gotta take a look in the documentation to see what it means instead of jumping to false conclusions! I don't believe it's always possible to make everything immediately obvious to an ignorant reader at the level of source code. If it would, we would not need documentation at all, would we? It's your imaginary library's author's responsibility to keep his code clean and optimal names also depend on the context the library is used in (not only how the tags are used with the library). Tags are just types -- typedef at will!
[...]
To fully understand what I meant with the "null tag" sentence above I have to explain what "(default)" in the reference means:
The semantics for unset aspects within a tag is equivalent to the one of the combination of all aspect tags marked with "(default)" (in the reference section) for these aspects, but with the exception that unset aspects cannot override set aspects in the context of tag combination.
There's another paragraph that needs work! Nevertheless, this has no bearing on readability, which is what I'm trying to address.
A peliminary attempt - it's not in, yet... <snip> -> "automatic conretization" <-
As to your point that "free_or_static" is better than "undecorated" in this case. I disagree. They are at least equivalent, and having one less tag to remember is better. After
In practice the one is absolutely neccessary and the other one /very/ useful in the context of classification.
A good name may handle both with aplomb. If not, one might be only be applicable in one context, another in the other context.
I don't think swamping the interface with aliases is a good idea. If the names provided by the library do not make sense in any particular case, create an alias for your case using 'typedef'.
For synthesis you can pick the one you like best. This is so, because there are no illegal tags in any context this way.
It still means there are multiple, interchangeable tags.
No. There no interchangable tags! There are some with similar semantics in the particular context of type synthesis (for the sake of a consistent logic and a very efficient implementation - not to give a toy to the user, see below).
all, your library will have to choose one to report as part of a type's kind, so a client might not choose to use the one the library chooses, so that client will need to know both.
Considering classification is a much more common use case than synthesis, the client most likely needs to know both, anyway.
However if it's only about synthesis - the client only has to know one.
I'm not sure I understand what you mean, here. Can you perhaps try to explain it differently?
You say a client needs to know both anyway. That's only true if
Let's be more precise: a client who fully wants to understand the logic.
both are available. You say the client only needs to know one if doing synthesis. I don't think it's clear at this point how common it will be for clients to only do synthesis with the library, so making a case on that basis is a straw man at best.
Right. But: the "whether or not to automatically concretize during synthesis" discussion is absolutely pointless: I am documenting it because it is defined behviour which is fundamental for the whole logic to work. Simple cases like this one: function_type< mpl::vector<int,int>, pointer >::type // == int(*)(int) would not work without it. I'm trying (obviously still without much success) to give the user chance to fully understand that logic. The examples only illustrate how things behave -- they do not recommend use cases! I should probably make this more obvious... Any ideas?
I tried to transform it and ended up with rewriting the whole sentence:
When a tag is created from a type, it completely describes all aspects of this type, so their variations are never abstract.
Feels smooth to me. Does it work?
Not quite. Maybe this will do:
A tag created from a type, it completely describes all of the aspects of the type. The aspect variations in the tag are never abstract.
Note that I left "abstract" in only because you used it and aren't convinced to do otherwise. I don't think it is appropriate.
The first sentence seems to be invalid due to restructuring artefacts. And a flaw crept in earlier: A tag does not describe the subtypes of a type, only its kind A tag created from a type, completely describes all aspects of the type's kind. The aspect variations in the tag are never abstract. Did we have this version, already?
result of the changes. Here's another stab that might be more accurate, and is certainly more succinct:
The tags in a type's kind are explicit, not abstract.
^^^^ You meant aspects here, I guess. Except this, in itself it's quite nice.
The problem is that I never was too happy with that "explicit" in the original and here the problem becomes even more obvious: it would need a full defintion.
I'm not sure it should use "abstract" either. At this point, however, I'm lost as to what should or shouldn't be abstract. Perhaps it would be good to put everything together and provide larger, in context, extracts to consider in toto.
Using the "runtime polymorphism analogy" again "creating a tag from a type" is in some ways similar to the behaviour of RTTI for polymorphic types: You get a type_info object describing the most derived type. I'll apply your suggestions and post a new revision of the complete draft after this message.
When using the tag metafunction to combine tags, it is possible to have tags representing different variations of the same aspect in the same list. When that occurs, the last variation is used; the others are ignored.
An adjustment is needed because of your previous s/combined/combined using the tag metafunction/-suggestion, so "tag metafunction" does not repeat.
I don't understand where the repetition is/will be.
Never mind!
"Same list" reads a little strange to me. It can be fixed easily by using "template argument list of 'tag'" instead.
I didn't like it a lot either. How about "tag's template argument list" instead and I think it will be fine.
We are talking about combination of tags anyway, so we might want to drop "when combining tags" as well.
Probably so.
While we're at stripping it down, I don't think it's important to explicitly say that it is possible and that other aspects are ignored.
How about:
When there are tags representing different variations of the same aspect in the template argument list of 'tag', the last variation is used.
Hmmm. I suppose you're right about the "it is possible" part, but I think the "ignored" part is helpful.
When there are tags representing different variations of the same aspect in tag's template argument list, the last variation is used; the others are ignored.
I like this.
Or maybe: s/is used/is dominant/
No.
Btw. I don't think it is neccessary to spell this out in more detail. There should be another more complex example, though.
OK.
Thanks, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Anyway, as you say, "variations" are semantic, not syntactic elements. Thus, they aren't concrete by definition, right? The
"Concrete" as opposed to "abstract" ?
Yes.
No, "variation" does not imply abstract or nonabstract.
Then it isn't semantic, right?
Can't see why it should imply this.
Let's forget about this. I don't think it helps us with the rest of the discussion anyway.
groups covered by a single tag are just that -- groups or combinations of tags.
The tags in the reference are all "aspect tags": One for each "variation" of each "aspect" there is.
Some represent groups of variations, right?
Well, not exactly. Some _match_ groups of (other) variations (in an appropriate context) *but* _represent_, well, /abstract/ concepts that include them.
In that sense, they do represent groups of variations. That is, "any_decoration" covers "reference_decoration" and the others. I don't mean that it is a bit pattern that includes the bits from the others, just that when you match reference_decoration, you can also match any_decoration. Having said that, however, it is not true that reference_decoration is a specialization of any_decoration. Instead, it's like color and red. Red is not a specialization of color; it's an instance or example of color. You could model this with a class called Color and one called Red, but you'd be much more likely to have Red be an instance of Color. If you then have an "any color" object, you would probably model that with a special Color instance, not with a base class for the normal colors. Thus, Red isn't a specialization of "any color" but just another Color. The special behavior of "any color" comes from how the library treats that instance. Since the library treats "any color" as matching any other Color, it can be thought of as containing--or at least representing--all of the other Colors. Similarly, reference_decoration and any_decoration are instances of decoration, and reference_decoration is not a specialization of any_decoration.
The "groups" you are talking about _are_ in fact _single_ variations of _single_ aspect tags.
Are we talking about the same thing? Yes, any_decoration is a single variation of the decoration aspect tag, but it represents all of the other variations. It is treated as a composite of the other variations.
Trying to give that a name seems misguided
Why?
Because there are lots of new terms already, and it isn't always necessary to give everything a name to discuss it.
"Aspect" and "variation" are proper English words, aren't they? Set into context by the preceding text.
It isn't that they are improper words or that they can't be set in context. It is that the cognitive effort needed to learn the vocabulary of the library can be more complicated than understanding the library itself. Just discussing the behavior and syntax may be sufficient in many cases. Creating a term for something can complicate matters.
unless it is a compound name like "variation set."
I like this one:
When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations make this possible.
(taken from your recent post)
We're making progress, however slow.
<snip>
-> what's wrong with "abstract?" <-
Precisely what I've been saying all along. It implies a generalization/specialization relationship that I don't see.
No. "Any-decoration" *includes* or *contains* "reference-decoration." It is not a generalization of it.
It does not *include* or *contain* anything (see above). It represents an abstraction; because of this it _matches_ "reference-decoration". In different context there is an "automatic concretization" (for which to document I need the term).
At this point, it seems we're in the middle of an "is not," "is too" argument.
The aspects variations in a tag are not identical, just like a pointer type to an abstract base and a pointer type to a concrete class are not identical.
Modeling each aspect with polymorphic classes, abstract variations would be abstract classes with the matches they bundle derived from them.
I think I've addressed that above. Furthermore, consider that you can't use a reference_decoration anywhere you can use an any_decoration, unless I'm sorely mistaken.
For me it fits (almost) perfectly. However, I'm not pedantic about it -- and if it really causes confusion I should probably change it; I'ld very much like to retrace your lines of thinking before doing this (and I'm currently having some difficulties with this), though.
I'm not sure it causes too much confusion, but I don't think it's the right analogy, so it doesn't help to clarify things. Composition seems right on target. Have I've helped you understand my thinking with this message?
A base class pointer is not a more abstracted version of a derived class pointer. They are both pointers. What is more and less abstract are the classes.
That's what I just said! Here's the analogy:
Class type O--O Aspect variation Pointer/Class instance O--O Aspect encoded in a Tag
I don't see it. A base class pointer can be used for both types. A derived class pointer can be used for only one. A reference_decoration can't be used where you need an any_decoration, so I don't think they fit well. Perhaps I'm just blind or dense.
Assuming special_aspect derived from (abstract base) aspect:
// distinct at type level is_same<aspect*,special_aspect*>::value == false
// "match" in the context of pointer assignment aspect* a1 = new special_aspect;
// "automatic concretization" in a generic factory typedef typename mpl::eval_if< is_abstract<T>
, concretize<T> , mpl::identity<T> >::type concrete_aspect; aspect* a2 = new aspect_type; ^^^^^^^^^^^ concrete_aspect?
I don't know what concretize<T> does, but I'm guessing you mean that this metaprogram magically produces special_aspect if T actually points to a special_aspect, so that concrete_aspect is special_aspect either way. I understand how you're trying to make the analogy between tags and pointers, but I don't see the analogy.
-> "any" vs. "unspecified" <-
Generalizing this the subtle difference:
"Give me whatever this means in this context, I won't specify it here"
instead of
"I don't care"
You can state that's what it means, but that's now what it means when one reads the code in ignorance. That is, consider the maintainer not familiar with the library. What does "unspecified" mean?
He's gotta take a look in the documentation to see what it means instead of jumping to false conclusions!
I don't believe it's always possible to make everything immediately obvious to an ignorant reader at the level of source code. If it would, we would not need documentation at all, would we?
That should be the goal. You can't always achieve it, but here I think you can.
It's your imaginary library's author's responsibility to keep his code clean and optimal names also depend on the context the library is used in (not only how the tags are used with the library). Tags are just types -- typedef at will!
I disagree with the onus for clarity in this case.
As to your point that "free_or_static" is better than "undecorated" in this case. I disagree. They are at least equivalent, and having one less tag to remember is better. After
In practice the one is absolutely neccessary and the other one /very/ useful in the context of classification.
A good name may handle both with aplomb. If not, one might be only be applicable in one context, another in the other context.
I don't think swamping the interface with aliases is a good idea. If the names provided by the library do not make sense in any particular case, create an alias for your case using 'typedef'.
I wasn't clear, but I meant make it so that they would only work in one context or the other. Then the names don't have to work for both contexts and can be made plain for the context to which they apply.
For synthesis you can pick the one you like best. This is so, because there are no illegal tags in any context this way.
It still means there are multiple, interchangeable tags.
No. There no interchangable tags!
There are some with similar semantics in the particular context of type synthesis (for the sake of a consistent logic and a very efficient implementation - not to give a toy to the user, see below).
Fine. I'm lost then and I'm sorry to say I can't spend much more time on this.
But: the "whether or not to automatically concretize during synthesis" discussion is absolutely pointless:
I am documenting it because it is defined behviour which is fundamental for the whole logic to work. Simple cases like this one:
function_type< mpl::vector<int,int>, pointer >::type // == int(*)(int)
would not work without it.
I'm trying (obviously still without much success) to give the user chance to fully understand that logic.
The examples only illustrate how things behave -- they do not recommend use cases! I should probably make this more obvious... Any ideas?
Not now. I'm sorry.
I tried to transform it and ended up with rewriting the whole sentence:
When a tag is created from a type, it completely describes all aspects of this type, so their variations are never abstract.
Feels smooth to me. Does it work?
Not quite. Maybe this will do:
A tag created from a type, it completely describes all of the aspects of the type. The aspect variations in the tag are never abstract.
Note that I left "abstract" in only because you used it and aren't convinced to do otherwise. I don't think it is appropriate.
The first sentence seems to be invalid due to restructuring artefacts.
Oops! You're right.
And a flaw crept in earlier: A tag does not describe the subtypes of a type, only its kind
OK.
A tag created from a type, completely describes all aspects of the type's kind. The aspect variations in the tag are never abstract.
Did we have this version, already?
I don't recall, but there should be no comma. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
groups covered by a single tag are just that -- groups or combinations of tags.
The tags in the reference are all "aspect tags": One for each "variation" of each "aspect" there is.
Some represent groups of variations, right?
Well, not exactly. Some _match_ groups of (other) variations (in an appropriate context) *but* _represent_, well, /abstract/ concepts that include them.
In that sense, they do represent groups of variations. That is, "any_decoration" covers "reference_decoration" and the others. I don't mean that it is a bit pattern that includes the bits from the others, just that when you match reference_decoration, you can also match any_decoration.
Having said that, however, it is not true that reference_decoration is a specialization of any_decoration. Instead, it's like color and red. Red is not a specialization of color; it's an instance or example of color. You could model this with a class called Color and one called Red, but you'd be much more likely to have Red be an instance of Color. If you then have an "any color" object, you would probably model that with a special Color instance, not with a base class for the normal colors. Thus, Red isn't a specialization of "any color" but just another Color.
Red is a color (and that's what counts). Whether it is good design to use inheritance here or not is pretty much a matter of what having that color means in your particular context (and if there is code or only data). "Color" is an abstract concept (at least by the Webster's-defintion): Something can be colored but can't in itself; it takes a particular color for something to be colored. <snip>
It isn't that they are improper words or that they can't be set in context. It is that the cognitive effort needed to learn the vocabulary of the library can be more complicated than understanding the library itself. Just discussing the behavior and syntax may be sufficient in many cases. Creating a term for something can complicate matters.
I agree. A lot of these problems should have been eliminated by now, though. http://lists.boost.org/boost/2005/07/29659.php http://lists.boost.org/boost/2005/07/29657.php
-> what's wrong with "abstract?" <-
Precisely what I've been saying all along. It implies a generalization/specialization relationship that I don't see.
I believe it's a matter from which perspective and with which level of abstraction we look at things. However I consider this point solved, since this part has been removed from the interface.
Have I've helped you understand my thinking with this message?
Yes, I think can understand your perspective looking at it. <snip>
Fine. I'm lost then and I'm sorry to say I can't spend much more time on this.
Fine with me. Thank you for your help! I enjoyed discussing with you. Regards, Tobias

Tag Types ---------- The Function Types library uses *tag* types in order to represent or query one or more aspects of a type's kind. Tags that represent the variations of a single aspect are called *aspect tags*. These tags can be used to determine whether one aspect of the type's kind matches a particular variation. is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T> When classifying types it is often necessary to match against several variations of one aspect. Special, *abstract* variations allow this behaviour. is_function< T, free_or_static > // the tag 'free_or_static' describes an abstract variation of the decoration // aspect and makes the above code equivalent to: mpl::or_< is_function_type< T, undecorated> , is_function_type< T, pointer > , is_function_type< T, reference > > Every aspect has at least one abstract variation, described by the (aspect) tag named "unspecfied_" plus the aspect name. This variation's primary purpose is to match any variation of an aspect; that is, to ignore that aspect in the context of type classification. is_function< T, unspecified_decoration >::value // true for any type T the library can handle Each abstract variation of an aspect has a non-abstract semantic equivalence 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 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, ... 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...) In the context of classification all aspects represented by the query tag must match: 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. 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. 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. function_type<void __cdecl(X::*)(),tag<undecorated,unspecified_call> > // ::type member is 'void(my_class&)' // the decoration and calling convention aspect are overridden

Tobias Schwinger <tschwinger@neoscientists.org> writes:
Tag Types ----------
The Function Types library uses *tag* types in order to represent or
Strike "in order."
query one or more aspects of a type's kind.
Such as...?
Tags that represent the variations of a single aspect are called *aspect tags*.
Strike "the."
These tags can be used to determine whether one aspect of the type's kind matches a particular variation.
is_function< T, variadic > is_function< T, pointer > // same as is_function_pointer<T>
Why are these not just "aspects of the type?" "Aspect of the type's kind" seems needlessly complex.
When classifying types it is often necessary to match against several variations of one aspect.
Okay, now you've introduced "variations of an aspect of a type's kind??!" Help! I'm drowning in jargon!
Special, *abstract* variations allow this behaviour.
is_function< T, free_or_static >
What aspect are "free" and "static" variations of? Oh, of the decoration aspect? Let's try this again: 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. 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: 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!] 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]
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!
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.
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]
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. ] 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,...). function_type< mpl::vector<int,int>, tag<pointer,variadic> >::type
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:
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)] The fully-general wildcard tag for any property not otherwise represented can be added to a tag specialization without changing its meaning. [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?]
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.]
function_type<void __cdecl(X::*)(),tag<undecorated,unspecified_call> > // ::type member is 'void(my_class&)' // the decoration and calling convention aspect are overridden
-- Dave Abrahams Boost Consulting www.boost-consulting.com

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 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

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

Hi Dave, Your previous post has brought up a very interesting point for me: I tried to completely specify the behaviour of the logic to give the user a chance to fully understand it and make things more transparent. It seems to me I've been "thinking too close to the implementation" and this approach is no good. ANNOTATION: I'll cut your post down to only refer to what still matters based on a conclusion drawn further below. David Abrahams wrote: <snip>
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.
I see. How about "Component types?" This term should be close enough to common terminology since we are talking about "compound types." Works?
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
Btw: "argument types" or "parameter types?"
You really don't intend to represent cv-qualification of member function pointers as simply the cv-qualification attached to the class type?
I do -- by default! Specifying these tags allows you to set/query either one of them explicitly. Because: ANNOTATION: I use const_member instead of const_ because it's its new name without trailing underscore. It will imply the 'member_pointer' decoration property then. a) is_const< typename class_of<T>::type >::value // precondition: T must be a member function pointer (decomposition) is_function<T,const_member>::value // no precondition (classification) b) mpl::not< is_const< typename class_of<T>::type > >::value // is lengthy is_function<T,non_const_member>::value // is not, plus it's more efficient c) function_type<MemFnPtr,[non_]const_member>::type // remove/add const from member function // NOTE: not specifying the const property in the context means keeping the // qualification of the original type (given the destination type will be a // member function pointer, that is). <snip> >> free_or_static <<
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.
This name was exchanged because the initial one I used ("unbound") was found to be too unexpressive.
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
...and also goes under "known issues", already.
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."
OK. It's the best so far. Sometimes the easiest solution seams the least obvious (not to mention that 'member' would have needed disambiguation too, caring about static members ;-) )...
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.
What 'decorated' means was already introduced (by the very first sentence of the documentation, see previous post). Generally I agree. However in this case it /should/ be mentioned because: template<typename T, typename Tag = undecorated> struct is_function; ^^^^^^^^^^^ The default argument, if no tag is given, makes 'is_function' only match function types (standard definition, compatible with TypeTraits). The "code-to-English-mapping" is like this: is_function<T> // "is T a function (not decorated)?" is_function<T,pointer> // "is T a function pointer?" is_function<T,variadic> // "is the function _in_ T variadic?" However, if too confusing I can introduce a version of 'is_function' with a single template parameter, change the name of the current 'is_function' to something else (e.g. "is_function_of_kind" -- better names are very welcome) and change its default argument. See: http://lists.boost.org/boost/2005/06/29480.php <snip>
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.
It's bought. With the first "function" removed, though. <snip>
// 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."
This issue was already expressed and "any" was proposed instead.
In this case the calling convention is very much being specified to be the default!
For this purpose, the proper name is "default_call."
Well "default_call" should not be a wildcard then. In classification context "default_call" should mean "detect whether this has default calling convention" (I had to think a moment about if these semantics are implementable -- they are). OK -- STOP. Can we remove the fully-general wildcards for each property from the interface, then? I believe we can: Classification: If you want to ignore a property just don't specify it in the query. Requirements: one wildcard to match any decoration /or/ to change the default argument of the class template currently called 'is_function' (as described above) Synthesis: You either override defaults or properties of an existing type. Requirements: there is a (in some ways special) 'default_call' calling convention.
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?
Sorry: "allow overriding of tag properties".
however, it maybe makes things more complicated to explain (see
<- (because it has to be documented anyway)
below) and involves more template instantiations - so I'm not sure it's really worth it.
<snip>
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."
Very nice! I believe it makes sense move this sentence to the part of the reference section on 'function_type' or 'tag'. Thank you very much for these comments! I'll reassmeble our points to a piece of documentation and post them later.

Tobias Schwinger wrote:
Can we remove the fully-general wildcards for each property from the interface, then?
Can we remove *any* wildcard tags from the interface (as there is only "nonmember" left)? I believe so! Introducing another traits class will do the trick: template<typename T> struct is_nonmember_callable_builtin; // not sure on this name suggestions welcome // matches function, function pointer and function reference types While we're at it: This probably makes 'is_function_pointer' and 'is_function_reference' less useful (because these can be treated uniformly because of function-to-pointer conversion in most cases). I'm not sure so I'll forward this post to Jonathan Turkanis' (who requested the feature) email address and hope he can comment on if and why dropping these templates would or would not work for him. Regards, Tobias

Tobias Schwinger wrote:
Tobias Schwinger wrote:
Can we remove the fully-general wildcards for each property from the interface, then?
Can we remove *any* wildcard tags from the interface (as there is only "nonmember" left)? I believe so!
Even better: we can remove the "decoration property" as well and put it entirely into the traits names. This way tags only represent additional attributation such as variadicness, calling convention and (overrides for) cv-qualification (for pointers to member functions only). Ignore the question from my previous post. It's been solved.

Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
<snip>
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.
I see. How about "Component types?"
That would be okay.
This term should be close enough to common terminology since we are talking about "compound types." Works?
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
Btw: "argument types" or "parameter types?"
Right, "parameter types."
You really don't intend to represent cv-qualification of member function pointers as simply the cv-qualification attached to the class type?
I do -- by default! Specifying these tags allows you to set/query either one of them explicitly.
Because:
ANNOTATION: I use const_member instead of const_ because it's its new name without trailing underscore. It will imply the 'member_pointer' decoration property then.
a) is_const< typename class_of<T>::type >::value // precondition: T must be a member function pointer (decomposition)
is_function<T,const_member>::value // no precondition (classification) b)
mpl::not< is_const< typename class_of<T>::type > >::value // is lengthy
is_function<T,non_const_member>::value // is not, plus it's more efficient
c)
function_type<MemFnPtr,[non_]const_member>::type // remove/add const from member function
// NOTE: not specifying the const property in the context means keeping the // qualification of the original type (given the destination type will be a // member function pointer, that is).
Okay, not bad.
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.
What 'decorated' means was already introduced (by the very first sentence of the documentation, see previous post).
Generally I agree. However in this case it /should/ be mentioned because:
template<typename T, typename Tag = undecorated> struct is_function; ^^^^^^^^^^^
The default argument, if no tag is given, makes 'is_function' only match function types (standard definition, compatible with TypeTraits).
The "code-to-English-mapping" is like this:
is_function<T> // "is T a function (not decorated)?" is_function<T,pointer> // "is T a function pointer?" is_function<T,variadic> // "is the function _in_ T variadic?"
I am unsure that supporting this default is well-advised. We already have is_function in the Type Traits library, no?
However, if too confusing I can introduce a version of 'is_function' with a single template parameter, change the name of the current 'is_function' to something else (e.g. "is_function_of_kind" -- better names are very welcome) and change its default argument.
has_properties? I assume you are in some nice nested namespace of Boost, with that suggestion.
<snip>
// 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."
This issue was already expressed and "any" was proposed instead.
"Any" is almost as bad as unspecified! You don't mean that it's some abitrary calling convention, but that it is the default calling convention.
In this case the calling convention is very much being specified to be the default!
For this purpose, the proper name is "default_call."
Well "default_call" should not be a wildcard then.
No, it should not.
In classification context "default_call" should mean "detect whether this has default calling convention" (I had to think a moment about if these semantics are implementable -- they are).
OK -- STOP.
Can we remove the fully-general wildcards for each property from the interface, then?
It seems like a good idea. In some sense you don't _have_ fully-general wildcards. I only thought you did because of the misleading use of "unspecified."
I believe we can:
Classification:
If you want to ignore a property just don't specify it in the query.
Yay!
Requirements: one wildcard to match any decoration /or/ to change the default argument of the class template currently called 'is_function' (as described above)
Yes, that would be fine.
Synthesis:
You either override defaults or properties of an existing type.
Requirements: there is a (in some ways special) 'default_call' calling convention.
Okay.
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?
Sorry: "allow overriding of tag properties".
I'm lost, sorry. Too much context is gone.
however, it maybe makes things more complicated to explain (see
<- (because it has to be documented anyway)
below) and involves more template instantiations - so I'm not sure it's really worth it.
<snip>
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."
Very nice! I believe it makes sense move this sentence to the part of the reference section on 'function_type' or 'tag'.
Thank you very much for these comments! I'll reassmeble our points to a piece of documentation and post them later.
You're welcome. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
<snip>
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.
What 'decorated' means was already introduced (by the very first sentence of the documentation, see previous post).
Generally I agree. However in this case it /should/ be mentioned because:
template<typename T, typename Tag = undecorated> struct is_function; ^^^^^^^^^^^
The default argument, if no tag is given, makes 'is_function' only match function types (standard definition, compatible with TypeTraits).
The "code-to-English-mapping" is like this:
is_function<T> // "is T a function (not decorated)?" is_function<T,pointer> // "is T a function pointer?" is_function<T,variadic> // "is the function _in_ T variadic?"
I am unsure that supporting this default is well-advised.
Me not either that's why I came to the following conclusion: Hide the decoration property from the interface and put it in traits classes. So you only have specify the tag to ask for attributation, such as a particular calling convention or whether it is variadic (matching any by default). // Result: bool, Concept: MPL-Integral Constant template<typename T, typename Tag = no_attributes> struct is_function; % % struct is_function_pointer; % % struct is_function_reference; % % struct is_member_function_pointer; % % struct is_callable_builtin; // any of the above % % struct is_callable_scalar; // any except undecorated % % struct is_nonmember_callable_builtin; // any except member pointers % % struct is_nonmember_callable_scalar; // function pointer or reference For the full synopsis see: http://lists.boost.org/boost/2005/07/29657.php Btw. would be awesome if you can afford the time and work to skim over it!
We already have is_function in the Type Traits library, no?
John and I agreed on that an ultimate goal to make them the same template. The only question left is whether the mere presence of a default argument hurts. See also: http://lists.boost.org/boost/2005/06/29297.php
However, if too confusing I can introduce a version of 'is_function' with a single template parameter, change the name of the current 'is_function' to something else (e.g. "is_function_of_kind" -- better names are very welcome) and change its default argument.
has_properties?
I assume you are in some nice nested namespace of Boost, with that suggestion.
Probably not necessary based on what the answer to that question (previous paragraph of this post) is. <snip>
Requirements: one wildcard to match any decoration /or/ to change the default argument of the class template currently called 'is_function' (as described above)
Yes, that would be fine.
Same question here: which one of the two possibilties? <snip>
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?
Sorry: "allow overriding of tag properties".
I'm lost, sorry. Too much context is gone.
I explained it again in the longest paragraph of this post: http://lists.boost.org/boost/2005/07/29669.php Thanks, Tobias

From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
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."
No way. "Nonmember" precludes static member functions. They may have the same type as nonmember functions, and aren't represented with member function pointers, but they are still member functions. We've discussed "unbound," "free," and a couple of other names. We've also noticed the "or" being a problem, but haven't found a fully satisfactory replacement. I suggested having both "free" and "static" names for the same thing, but we didn't like the duplication. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
Tobias Schwinger <tschwinger@neoscientists.org> writes:
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."
No way. "Nonmember" precludes static member functions. They may have the same type as nonmember functions, and aren't represented with member function pointers, but they are still member functions.
Way. We are not talking about the functions, we're talking about their types. In other words, the traits do not inspect individual values of int (*)(int) -- they inspect the type int(*)(int) itself. I don't think there's any problem with calling int(*)(int) a nonmember function pointer type. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
From: David Abrahams <dave@boost-consulting.com>
suggested terminology works. So "free_or_static" should be "nonmember."
No way. "Nonmember" precludes static member functions. They may have the same type as nonmember functions, and aren't represented with member function pointers, but they are still member functions.
Way. We are not talking about the functions, we're talking about their types. In other words, the traits do not inspect individual values of int (*)(int) -- they inspect the type int(*)(int) itself. I don't think there's any problem with calling int(*)(int) a nonmember function pointer type.
If you're thinking about whether the type is that of a static member function, then you won't be thinking that you should use "nonmember." -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
Way. We are not talking about the functions, we're talking about their types. In other words, the traits do not inspect individual values of int (*)(int) -- they inspect the type int(*)(int) itself. I don't think there's any problem with calling int(*)(int) a nonmember function pointer type.
If you're thinking about whether the type is that of a static member function, then you won't be thinking that you should use "nonmember."
Just to be pedantic, the types of member functions are regular function types also. Furthermore, you *can* have cv-qualified function types, such as 'int (int) const'. The differences are that you cannot declare a non-member function with a cv-qualified function type and that the types of pointers to actual functions differ based on whether they are (non-static) member functions. E.g. typedef void func(); func f; struct x { func f; }; &f -> void (*)() &x::f -> void (x::*)() Likewise: template<class> struct remove_pointer_to_member; template<class R, class C> struct remove_pointer_to_member { typedef R type; }; remove_pointer_to_member< void (x::*)() >::type -> void () Basically, the argument between member and non-member doesn't apply to function types. If, OTOH, you're really talking about pointers to functions and pointers to member functions, then a type difference becomes evident and there is a significant distinction. In that case, the types are "pointers to function" (which is the type classification of a pointer to static member function) and "pointer to member function" (which is the type classification of a pointer to non-static member function). I think it is a misuse of terminology to say "the type of a function" and really mean "the type of a pointer to function." Regards, Paul Mensonides

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Paul Mensonides
template<class> struct remove_pointer_to_member;
template<class R, class C> struct remove_pointer_to_member { typedef R type; };
oops... the specialization should be 'remove_pointer_to_member<R C::*>'... Regards, Paul Mensonides

Hi Paul, allow me to add a few annotations in regard to the library and its documentation. Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
Way. We are not talking about the functions, we're talking about their types. In other words, the traits do not inspect individual values of int (*)(int) -- they inspect the type int(*)(int)
itself. I
don't think there's any problem with calling int(*)(int) a
nonmember
function pointer type.
If you're thinking about whether the type is that of a static member function, then you won't be thinking that you should use "nonmember."
Just to be pedantic, the types of member functions are regular function types also.
To be even more pedantic: there are no types of member function types (there are only function types decorated with a pointer to member which as a whole are 'compound non-function types'). But it seems I look at it the very same way: 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. (this is a cite from the very first sentence introducing the library - this revised version of the docs has not been posted yet, however)
Furthermore, you *can* have cv-qualified function types, such as 'int (int) const'.
While theoretically correct, things are too implementation-defined around here to rely on that you can do anything with cv-qualified function types (not decorated with a pointer to member, that is). E.g: typedef int(int) const x; // parse error with GCC We shouldn't use types like this -- this is the reason why the library does not support them.
The differences are that you cannot declare a non-member function with a cv-qualified function type and that the types of pointers to actual functions differ based on whether they are (non-static) member functions. E.g.
typedef void func();
func f;
struct x { func f; };
&f -> void (*)() &x::f -> void (x::*)()
Likewise:
template<class> struct remove_pointer_to_member;
template<class R, class C> struct remove_pointer_to_member { typedef R type; };
remove_pointer_to_member< void (x::*)() >::type -> void ()
Yeah. For the protocol: this code won't work with GCC (doesn't match the specialization) or MSVC ( R is substituted with void __thiscall(x::*)() ). The fact that there can be calling conventions particular to member-functions makes these "add/remove member pointer transformations" even more troublesome.
Basically, the argument between member and non-member doesn't apply to function types. If, OTOH, you're really talking about pointers to functions and pointers to member functions, then a type difference becomes evident and there is a significant distinction. In that case, the types are "pointers to function" (which is the type classification of a pointer to static member function) and "pointer to member function" (which is the type classification of a pointer to non-static member function). I think it is a misuse of terminology to say "the type of a function" and really mean "the type of a pointer to function."
The review version of the library redefined and widened the term "function type" for that matter. I never really liked it and the boostified version will pedantically use the term "function type" as defined by the standard and will not refer to a function pointer as being a function type! Regards, Tobias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
Just to be pedantic, the types of member functions are regular function types also.
To be even more pedantic: there are no types of member function types (there are only function types decorated with a pointer to member which as a whole are 'compound non-function types'). But it seems I look at it the very same way:
I disagree. The type of a member function is a regular function type. Note that type equivalence does not imply functional equivalence (i.e. how it works). The notion of 'type' is only a conceptual abstraction. Regardless, the type of a member function is a regular function type, even though the type of a pointer-to-member-function differs significantly from a pointer-to-function.
Furthermore, you *can* have cv-qualified function types, such as 'int (int) const'.
While theoretically correct, things are too implementation-defined around here to rely on that you can do anything with cv-qualified function types (not decorated with a pointer to member, that is). E.g:
typedef int(int) const x; // parse error with GCC
Should be a parse error on any compiler. typedef int x(int) const; // correct
We shouldn't use types like this -- this is the reason why the library does not support them.
I understand (though don't entirely agree with) your motivation for this. There isn't much you can do with cv-qualified function types, and there are a load of gray areas (even in the standard). Another fun one is exception specifications.
remove_pointer_to_member< void (x::*)() >::type -> void ()
Yeah. For the protocol: this code won't work with GCC (doesn't match the specialization) or MSVC ( R is substituted with void __thiscall(x::*)() ).
I know. For the record, however, both GCC and MSVC are wrong. It should match the specialization and the result should be 'void ()'.
The fact that there can be calling conventions particular to member-functions makes these "add/remove member pointer transformations" even more troublesome.
It is particularly annoying that there's a separate calling convention for this. It is totally unnecessary. I'd be more than happy if we could get rid of the inferior __stdcall calling convention also. Note also that calling convention is properly in the domain of "extra-linguistic instructions to the compiler" and should be implemented with pragmas. This is especially true if C++ picks up C99's _Pragma operator which can be the result of a macro expansion. E.g. #define __stdcall _Pragma("__stdcall")
non-static member function). I think it is a misuse of terminology to say "the type of a function" and really mean "the type of a pointer to function."
The review version of the library redefined and widened the term "function type" for that matter. I never really liked it and the boostified version will pedantically use the term "function type" as defined by the standard and will not refer to a function pointer as being a function type!
That's fine with me. I only really commented to point out that there is no "member function type" as a distinct entity. I don't think that 'nonmember' is a property of a function type--it just doesn't make sense. Regards, Paul Mensonides

Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
Just to be pedantic, the types of member functions are
regular function types
also.
To be even more pedantic: there are no types of member function types (there are only function types decorated with a pointer to member which as a whole are 'compound non-function types'). But it seems I look at it the very same way:
I disagree. The type of a member function is a regular function type. Note that type equivalence does not imply functional equivalence (i.e. how it works). The notion of 'type' is only a conceptual abstraction. Regardless, the type of a member function is a regular function type, even though the type of a pointer-to-member-function differs significantly from a pointer-to-function.
It's essentially saying the same thing, but I got your nuance: whether member or nonmember has nothing to do with the function type and only with the result type of operator& (or function-to-pointer conversion) applied an entity of that type.
Furthermore, you *can* have cv-qualified function types,
such as 'int
(int) const'.
While theoretically correct, things are too implementation-defined around here to rely on that you can do anything with cv-qualified function types (not decorated with a pointer to member, that is). E.g:
typedef int(int) const x; // parse error with GCC
Should be a parse error on any compiler.
typedef int x(int) const; // correct
Yeah, right -- actually I know -- just posted too quickly (shame on me). Still doesn't compile with GCC, though ("invalid specifier").
We shouldn't use types like this -- this is the reason why the library does not support them.
I understand (though don't entirely agree with) your motivation for this. There isn't much you can do with cv-qualified function types, and there are a load of gray areas (even in the standard). Another fun one is exception specifications.
In more detail: Given a compiler allows CV-qualified functions, these types pass the library without problems; the library detects them properly because top-level cv-qulification is ignored. There is no way to emphasize a query or specification for the cv-qualification of nonmember callable builtin types, which would involve adding overhead for an esoteric and unportable feature.
remove_pointer_to_member< void (x::*)() >::type -> void ()
Yeah. For the protocol: this code won't work with GCC (doesn't match the specialization) or MSVC ( R is substituted with void __thiscall(x::*)() ).
I know. For the record, however, both GCC and MSVC are wrong. It should match the specialization and the result should be 'void ()'.
That's what I meant; I should've added "EDG and Borland do it right".
The fact that there can be calling conventions particular to member-functions makes these "add/remove member pointer transformations" even more troublesome.
It is particularly annoying that there's a separate calling convention for this. It is totally unnecessary. I'd be more than happy if we could get rid of the inferior __stdcall calling convention also. Note also that calling convention is properly in the domain of "extra-linguistic instructions to the compiler" and should be implemented with pragmas. This is especially true if C++ picks up C99's _Pragma operator which can be the result of a macro expansion. E.g.
#define __stdcall _Pragma("__stdcall")
C99's _Pragma seems pretty close to GCC's "__attribute__(whatever)"... Because of your awesome Boost.Preprocessor, my library does not have to worry about this sort of changes at all (its just a tuple element in the configuration) ;-).
non-static member function). I think it is a misuse of
terminology to say "the
type of a function" and really mean "the type of a pointer
to function."
The review version of the library redefined and widened the term "function type" for that matter. I never really liked it and the boostified version will pedantically use the term "function type" as defined by the standard and will not refer to a function pointer as being a function type!
That's fine with me. I only really commented to point out that there is no "member function type" as a distinct entity. I don't think that 'nonmember' is a property of a function type--it just doesn't make sense.
I use the terms "callable scalar type" (pointer/reference/member pointer to function) and "callable builtin type" (like "callable scalar" but includes function types) in identifier names which involve 'nonmember'. The term "member" is only used in combination with "function pointer" and within the property tags "const_member" and "volatile_member" ("member" indicates they are ignored for any non-member-function-pointer). Thanks for your reply which made me clarify my post. Regards, Tobias

Tobias Schwinger wrote:
Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
Just to be pedantic, the types of member functions are
regular function types
also.
To be even more pedantic: there are no types of member function types (there are only function types decorated with a pointer to member which as a whole are 'compound non-function types'). But it seems I look at it the very same way:
I disagree. The type of a member function is a regular function type. Note that type equivalence does not imply functional equivalence (i.e. how it works). The notion of 'type' is only a conceptual abstraction. Regardless, the type of a member function is a regular function type, even though the type of a pointer-to-member-function differs significantly from a pointer-to-function.
It's essentially saying the same thing, but I got your nuance: whether member or nonmember has nothing to do with the function type and only with the result type of operator& (or function-to-pointer conversion) applied an entity of that type.
Furthermore, you *can* have cv-qualified function types,
such as 'int
(int) const'.
While theoretically correct, things are too implementation-defined around here to rely on that you can do anything with cv-qualified function types (not decorated with a pointer to member, that is). E.g:
typedef int(int) const x; // parse error with GCC
Should be a parse error on any compiler.
typedef int x(int) const; // correct
Yeah, right -- actually I know -- just posted too quickly (shame on me). Still doesn't compile with GCC, though ("invalid specifier").
We shouldn't use types like this -- this is the reason why the library does not support them.
I understand (though don't entirely agree with) your motivation for this. There isn't much you can do with cv-qualified function types, and there are a load of gray areas (even in the standard). Another fun one is exception specifications.
In more detail: Given a compiler allows CV-qualified functions, these types pass the library without problems; the library detects them properly because top-level cv-qulification is ignored. There is no way to emphasize a query or specification for the cv-qualification of nonmember callable builtin types, which would involve adding overhead for an esoteric and unportable feature.
remove_pointer_to_member< void (x::*)() >::type -> void ()
Yeah. For the protocol: this code won't work with GCC (doesn't match the specialization) or MSVC ( R is substituted with void __thiscall(x::*)() ).
I know. For the record, however, both GCC and MSVC are wrong. It should match the specialization and the result should be 'void ()'.
That's what I meant; I should've added "EDG and Borland do it right".
The fact that there can be calling conventions particular to member-functions makes these "add/remove member pointer transformations" even more troublesome.
It is particularly annoying that there's a separate calling convention for this. It is totally unnecessary. I'd be more than happy if we could get rid of the inferior __stdcall calling convention also. Note also that calling convention is properly in the domain of "extra-linguistic instructions to the compiler" and should be implemented with pragmas. This is especially true if C++ picks up C99's _Pragma operator which can be the result of a macro expansion. E.g.
#define __stdcall _Pragma("__stdcall")
C99's _Pragma seems pretty close to GCC's "__attribute__(whatever)"...
Because of your awesome Boost.Preprocessor, my library does not have to worry about this sort of changes at all (its just a tuple element in the configuration) ;-).
non-static member function). I think it is a misuse of
terminology to say "the
type of a function" and really mean "the type of a pointer
to function."
The review version of the library redefined and widened the term "function type" for that matter. I never really liked it and the boostified version will pedantically use the term "function type" as defined by the standard and will not refer to a function pointer as being a function type!
That's fine with me. I only really commented to point out that there is no "member function type" as a distinct entity. I don't think that 'nonmember' is a property of a function type--it just doesn't make sense.
I use the terms "callable scalar type" (pointer/reference/member pointer to function) and "callable builtin type" (like "callable scalar" but includes function types) in identifier names which involve 'nonmember'.
The term "member" is only used in combination with "function pointer" and within the property tags "const_member" and "volatile_member" ("member" indicates they are ignored for any non-member-function-pointer). ^^^^^^^^^^^^^^^^^^^^ Should be non-member-function-pointer-callable-builtin-type (and I won't use such a term in the documentation :-) ).
Thanks for your reply which made me clarify my post.
Regards,
Tobias
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
It's essentially saying the same thing, but I got your nuance: whether member or nonmember has nothing to do with the function type and only with the result type of operator& (or function-to-pointer conversion) applied an entity of that type.
Exactly. It is one of those places where the type system cheats internally.
In more detail: Given a compiler allows CV-qualified functions, these types pass the library without problems; the library detects them properly because top-level cv-qulification is ignored.
I'm not sure what you mean here, but it makes me wary. You cannot catch the cv-qualification of a function with 'const T'. I.e. typedef void func(); const func != void () const (In fact, 'const func' is illegal.)
There is no way to emphasize a query or specification for the cv-qualification of nonmember callable builtin types, which would involve adding overhead for an esoteric and unportable feature.
I assume that you mean compile-time overhead. If you have support for pointers to cv-qualified member functions, it seems (to me) that the required boilerplate to deal with cv-qualified function types is already there. If you don't have support for cv-qualified member functions, then you should; they are not esoteric at all. The only reason for library support for them (cv-qualified function types), IMO, is completeness. I'm not saying that it is particularly useful.
#define __stdcall _Pragma("__stdcall")
C99's _Pragma seems pretty close to GCC's "__attribute__(whatever)"...
Incidentally, this brings up annoying thing #3. C++ already sort-of has a language-level facility for this kind of thing--e.g. extern "C". Calling convention could be part of such a linkage specification. In the case of __stdcall, extern "verbose". Of course, the annoying part is that you can't touch anything with this kind of linkage specification with templates--though you should be able to.
Because of your awesome Boost.Preprocessor, my library does not have to worry about this sort of changes at all (its just a tuple element in the configuration) ;-).
Once again, the preprocessor to the rescue! Regards, Paul Mensonides

Paul Mensonides wrote:
Incidentally, this brings up annoying thing #3. C++ already sort-of has a language-level facility for this kind of thing--e.g. extern "C". Calling convention could be part of such a linkage specification. In the case of __stdcall, extern "verbose".
Apologies for the OT, but why "verbose"? __stdcall isn't verbose at all. f( x, y ), __cdecl: push y push x call _f add esp, 8 __stdcall: push x push y call _f@8

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Peter Dimov
Calling convention could be part of such a linkage specification. In the case of __stdcall, extern "verbose".
Apologies for the OT, but why "verbose"? __stdcall isn't verbose at all.
Sorry, underhanded (yet well-deserved) shot at Pascal. Regards, Paul Mensonides

Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Peter Dimov
Calling convention could be part of such a linkage
specification. In
the case of __stdcall, extern "verbose".
Apologies for the OT, but why "verbose"? __stdcall isn't verbose at all.
Sorry, underhanded (yet well-deserved) shot at Pascal. ^ ;-) ^
Btw. "__pascal" and "__stdcall" are not exactly the same: Both require the callee to clean up but the arguments are ordered differently on the stack. Regards, Tobias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
Apologies for the OT, but why "verbose"? __stdcall isn't verbose at all.
Sorry, underhanded (yet well-deserved) shot at Pascal. ^ ;-) ^
Btw. "__pascal" and "__stdcall" are not exactly the same: Both require the callee to clean up but the arguments are ordered differently on the stack.
Hmm, didn't know there was a difference. In any case, the callee cleanup is the part that makes it inferior to __cdecl. It isn't as general, both for variadics and possible tail-recursion optimizations--particularly in mutually tail-recursive functions: int g(int x); int f(int x) { return g(x); } int g(int x) { return f(x); } (Yes, I know there is no termination.) The point is that the compiler could push 'x' onto the stack from external code, but 'f' and 'g' could call each other repeatedly without touching the stack at all, and then when the call actually does return to the external code, the external code can pop 'x' from the stack. This can work even if 'f' and 'g' are separately compiled (i.e. not optimized as a unit). This doesn't work under 'callee cleanup' without extra scaffolding because the callee cannot know if 'x' should be popped. Regards, Paul Mensonides

Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
Apologies for the OT, but why "verbose"? __stdcall isn't verbose at all.
Sorry, underhanded (yet well-deserved) shot at Pascal.
^ ;-) ^
Btw. "__pascal" and "__stdcall" are not exactly the same: Both require the callee to clean up but the arguments are ordered differently on the stack.
Hmm, didn't know there was a difference. In any case, the callee cleanup is the part that makes it inferior to __cdecl. It isn't as general, both for variadics
Variadics would require some sort of "dynamic cleanup" if done at the callee-site (I doubt there is any compiler out there implementing ugly and crazy stuff like this)...
and possible tail-recursion optimizations--particularly in mutually tail-recursive functions:
int g(int x);
int f(int x) { return g(x); }
int g(int x) { return f(x); }
(Yes, I know there is no termination.) The point is that the compiler could push 'x' onto the stack from external code, but 'f' and 'g' could call each other repeatedly without touching the stack at all, and then when the call actually does return to the external code, the external code can pop 'x' from the stack.
This kind of "stack frame recycling" is attractive, indeed. You may still be able to request it more explicitly (without relying on optimization at all) by using an equivalent, iterative algorithm ;-).
This can work even if 'f' and 'g' are separately compiled (i.e. not optimized as a unit).
Say we split it into two translation units. The compiler sees this code int g(int x); int f(int x) { return g(x); } and cannot know what g does, so the full code generation for the call must happen in the linker. How does the linker then know the callee doesn't change 'x' and it's legal to reuse the stack frame here? Does the other object file contain this kind of information?
This doesn't work under 'callee cleanup' without extra scaffolding because the callee cannot know if 'x' should be popped.
Well, the callee always cleans up. So we'ld have to "unpop" the values at the call-site to reuse the stack frame and add unecessary code. This code, however, can be theoretically eliminated in the CPU at runtime: add esp,4 sub esp,2 can be, given there are no instructions in between that use the stack pointer register (these side-effects are tracked anyway for pipelining), transformed to add esp,2 Further there are numerous situation where stack reuse isn't applicable and caller cleanup involves more code at the call-site, so I believe __stdcall has its place. The only quite useless calling convention I see, talking x86, is __fastcall, which attempts to use CPU registers for the argument values. Basically it might have been a good idea but this CPU has too few and not even all-purpose registers for __fastcall to make much sense (except for very tiny functions, perhaps). Thanks, Tobias

Paul Mensonides wrote:
In more detail: Given a compiler allows CV-qualified functions, these types pass the library without problems; the library detects them properly because top-level cv-qulification is ignored.
I'm not sure what you mean here, but it makes me wary.
The library uses the TypeTraits template 'remove_cv'. I n theory e.g: template<typename T> struct remove_const { typedef T type; }; template<typename T> struct remove_const<T const> { typedef T type; }; should work, shouldn't it? In practice it depends on the compiler, of course.
There is no way to emphasize a query or specification for the cv-qualification of nonmember callable builtin types, which would involve adding overhead for an esoteric and unportable feature.
I assume that you mean compile-time overhead.
What else could I possibly mean here?
If you have support for pointers to cv-qualified member functions, it seems (to me) that the required boilerplate to deal with cv-qualified function types is already there. If you don't have support for cv-qualified member functions, then you should; they are not esoteric at all.
Sure I have (btw. it would've not passed the review without, I guess) - but only for the function types in member function pointers. Implementing things differently would mean a lot of portability-trouble.
The only reason for library support for them (cv-qualified function types), IMO, is completeness. I'm not saying that it is particularly useful.
In a perfect world (where your "remove_member_pointer" template always works) I'ld support them. However, currently I don't see that completeness outweighs its price here. Further I believe it's a good idea to keep the user away from dark corners of the language by design. Regards, Tobias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
In more detail: Given a compiler allows CV-qualified functions, these types pass the library without problems; the library detects them properly because top-level cv-qulification is ignored.
I'm not sure what you mean here, but it makes me wary.
The library uses the TypeTraits template 'remove_cv'. I
n theory e.g:
template<typename T> struct remove_const { typedef T type; }; template<typename T> struct remove_const<T const> { typedef T type; };
should work, shouldn't it? In practice it depends on the compiler, of course.
That will remove any cv-qualifiers on a pointer to function (as in a "const pointer to function"), but it won't remove the cv-qualifiers from a raw function type. There is no way to add or remove such qualifiers without taking the type apart and putting it back together with or without the cv-qualification.
There is no way to emphasize a query or specification for the cv-qualification of nonmember callable builtin types, which would involve adding overhead for an esoteric and unportable feature.
I assume that you mean compile-time overhead.
What else could I possibly mean here?
I'm not familiar with all that your library does, so, from my point of view, there might be a runtime component to the library. I assume that you mean compile-time overhead, but I don't see why there has to be. Say you where going to support them only on compilers that deal with the properly. All it takes is to defer them to the implementation of pointers-to-member-functions. I.e. say that you have 'is_pointer_to_const_member_function', then you can make 'is_const_function' without any (significant) overhead: struct C { }; template<class T> struct is_const_function : is_pointer_to_const_member_function<T C::*> { }; Granted, you have to do a little more than that (by eliminating those types that cannot be the subject of a pointer-to-member--such as references), but it isn't that hard. It also isn't too much of a burden to say: this metafunction doesn't work on x, y, and z compilers.
If you have support for pointers to cv-qualified member functions, it seems (to me) that the required boilerplate to deal with cv-qualified function types is already there. If you don't have support for cv-qualified member functions, then you should; they are not esoteric at all.
Sure I have (btw. it would've not passed the review without, I guess) - but only for the function types in member function pointers. Implementing things differently would mean a lot of portability-trouble.
I understand.
The only reason for library support for them (cv-qualified function types), IMO, is completeness. I'm not saying that it is particularly useful.
In a perfect world (where your "remove_member_pointer" template always works) I'ld support them. However, currently I don't see that completeness outweighs its price here. Further I believe it's a good idea to keep the user away from dark corners of the language by design.
If that is the case, then you shouldn't be supporting open variadics. Support for that adds significant overhead to the implementation. Granted, variadic function types are more common than cv-qualified function types, but they are still quite rare. Regards, Paul Mensonides

Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
In more detail: Given a compiler allows CV-qualified
functions, these
types pass the library without problems; the library detects them properly because top-level cv-qulification is ignored.
I'm not sure what you mean here, but it makes me wary.
The library uses the TypeTraits template 'remove_cv'. I
n theory e.g:
template<typename T> struct remove_const { typedef T type; }; template<typename T> struct remove_const<T const> { typedef T type; };
should work, shouldn't it? In practice it depends on the compiler, of course.
That will remove any cv-qualifiers on a pointer to function (as in a "const pointer to function"), but it won't remove the cv-qualifiers from a raw function type. There is no way to add or remove such qualifiers without taking the type apart and putting it back together with or without the cv-qualification.
Is either way defined behaviour? Got some standard references for me, perhaps?
There is no way to emphasize a query or specification for the cv-qualification of nonmember callable builtin types, which would involve adding overhead for an esoteric and
unportable feature.
I assume that you mean compile-time overhead.
What else could I possibly mean here?
I'm not familiar with all that your library does, so, from my point of view, there might be a runtime component to the library. I assume that you mean compile-time overhead, but I don't see why there has to be.
Oh! I'm sorry -- assumed there was enough context around.
Say you where going to support them only on compilers that deal with the properly. All it takes is to defer them to the implementation of pointers-to-member-functions. I.e. say that you have 'is_pointer_to_const_member_function', then you can make 'is_const_function' without any (significant) overhead:
struct C { };
template<class T> struct is_const_function : is_pointer_to_const_member_function<T C::*> { };
Granted, you have to do a little more than that (by eliminating those types that cannot be the subject of a pointer-to-member--such as references), but it isn't that hard. It also isn't too much of a burden to say: this metafunction doesn't work on x, y, and z compilers.
In this particular case it doesn't cost much. But if I'm going to do a trivial thing as finding out whether 'int' is a (any cv-qualified) function I need a second non-trivial template instantiation and a couple of trivial ones as you mentioned already. I'm not sure this feature is worth its price. Further, if your compiler is smart enough you can easily write it yourself if you need it.
If you have support for pointers to cv-qualified member functions, it seems (to me) that the
required
boilerplate to deal with cv-qualified function types is
already there.
If you don't have support for cv-qualified member
functions, then you
should; they are not esoteric at all.
Sure I have (btw. it would've not passed the review without, I guess) - but only for the function types in member function pointers. Implementing things differently would mean a lot of portability-trouble.
I understand.
The only reason for library support for them (cv-qualified function types), IMO, is completeness. I'm not saying that it is
particularly useful.
In a perfect world (where your "remove_member_pointer" template always works) I'ld support them. However, currently I don't see that completeness outweighs its price here. Further I believe it's a good idea to keep the user away from dark corners of the language by design.
If that is the case, then you shouldn't be supporting open variadics. Support for that adds significant overhead to the implementation. Granted, variadic function types are more common than cv-qualified function types, but they are still quite rare.
Can't really say 'printf' is a dark corner of the language... "Dark history", perhaps. And open variadics can be quite useful. We shouldn't make assumptions on how many people use them -- variadic functions have been there for a long time. Thanks, Tobias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
That will remove any cv-qualifiers on a pointer to function (as in a "const pointer to function"), but it won't remove the cv-qualifiers from a raw function type. There is no way to add or remove such qualifiers without taking the type apart and putting it back together with or without the cv-qualification.
Is either way defined behaviour? Got some standard references for me, perhaps?
----- 8.3.5/4 A cv-qualifier-seq shall only be part of the function type for a nonstatic member function, the function type to which a pointer to member refers, or the top-level function type of a function typedef declaration. The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type, i.e., it does not create a cv-qualified function type. In fact, if at any time in the determination of a type a cv-qualified function type is formed, the program is ill-formed. ----- There might be more references, but this gives a significantly strong implication that cv-qualification on function types is radically different than normal cv-qualification. The cv-qualifiers are modifying the implicit 'this' parameter. I.e. the cv-qualifiers don't modify the function type (all functions are 'const' because C++ doesn't treat functions as first-class objects); they modify an implicit formal parameter. So attempting to remove cv-qualification this way would be akin to transforming 'void (const int*)' into 'void (int*)'.
I'm not familiar with all that your library does, so, from my point of view, there might be a runtime component to the library. I assume that you mean compile-time overhead, but I don't see why there has to be.
Oh! I'm sorry -- assumed there was enough context around.
There probably is, but I haven't been reading all of it. Given the nature of your library, I thought it unlikely that there was a runtime component and therefore assumed that you were referring to static overhead.
Say you where going to support them only on compilers that deal with the properly. All it takes is to defer them to the implementation of pointers-to-member-functions. I.e. say that you have 'is_pointer_to_const_member_function', then you can make 'is_const_function' without any (significant) overhead:
struct C { };
template<class T> struct is_const_function : is_pointer_to_const_member_function<T C::*> { };
Granted, you have to do a little more than that (by eliminating those types that cannot be the subject of a pointer-to-member--such as references), but it isn't that hard. It also isn't too much of a burden to say: this metafunction doesn't work on x, y, and z compilers.
In this particular case it doesn't cost much. But if I'm going to do a trivial thing as finding out whether 'int' is a (any cv-qualified) function I need a second non-trivial template instantiation and a couple of trivial ones as you mentioned already. I'm not sure this feature is worth its price. Further, if your compiler is smart enough you can easily write it yourself if you need it.
Yes. On the same token, however, I can just as easily write any other sort of function type manipulation that I might need. The point is that a library like yours should prevent the need for me to do it. If the feature is not used, the only possible *significant* compile-time overhead that I see is preprocessing. This can be solved by making headers more granular (not a commentary on your library) and simply not including it. If it is used, then the user pays for it with a few template instantiations--just like anything else. From an implementation point-of-view (meaning the cost on your time personally), supporting this would be fairly easy if you don't try to make it work on compilers that are fundamentally broken in this area.
If that is the case, then you shouldn't be supporting open variadics. Support for that adds significant overhead to the implementation. Granted, variadic function types are more common than cv-qualified function types, but they are still quite rare.
Can't really say 'printf' is a dark corner of the language...
The type of 'printf' may have C linkage which you can't do anything with on any conforming compiler. Basically, 'printf' is untouchable (in this context) in portable code.
"Dark history", perhaps. And open variadics can be quite useful. We shouldn't make assumptions on how many people use them -- variadic functions have been there for a long time.
Trust me, I'm a big fan of the concept of variadics. Given "reasonable" language support, they are a very enabling feature for a variety of things. (This is one of the reasons why I'm glad that C is still around. IMO, C++ tends to overlook the fundamental building blocks (e.g. procedural programming) as it grows. In some sense, C keeps C++ grounded. Of course, C is not the be all and end all of procedural programming. By now, we should have nested functions, with them comes closures, and with closures comes anonymous functions (i.e. lambda functions). These are fundamental building blocks.) Unfortunately, we don't yet have reasonable variadic support in C++. We need typesafe variadic functions, variadic templates, and variadic macros. However right now, given that argument lists are an iterative syntactic structure (currently at odds with generic programming), that current variadic functions aren't typesafe (at odds with generic programming), and that you can't portably pass anything to them except POD's (at odds with generic programming)--it's a safe bet that function type manipulation (which would likely be done in generic code) of variadic function types will be extremely rare. Variadic functions (specifically, how to use them even to the point of how to invoke them) are way too semantically dependent on extra-linguistic knowledge like documentation. I certainly don't think you should remove support for them--I just see its utility as on par with cv-qualified function types--yet supporting it effectively doubles all of the template specializations required. I don't buy the 'cost' argument as opposed to the 'completeness' argument, but I'm not terribly concerned over the lack of support. However, I'm a would-be user of a library, not the library author. If I was the library author, completeness would be a worthwhile goal in and of itself--it is a requirement for mastery of the subject. As a library author in other areas, the most annoying limitations are often those corner cases that you can do nothing about (and this isn't one of them), but present a barrior to completeness. It's the difference between "as good as can be given x, y, and z" and "ideal". My disagreement is more of a disagreement with perspective rather than over a particular feature. Regards, Paul Mensonides

Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
That will remove any cv-qualifiers on a pointer to function
(as in a
"const pointer to function"), but it won't remove the cv-qualifiers from a raw function type. There is no way to add or remove such qualifiers without taking the type apart and putting it
back together with or without the cv-qualification.
Is either way defined behaviour? Got some standard references for me, perhaps?
----- 8.3.5/4
A cv-qualifier-seq shall only be part of the function type for a nonstatic member function, the function type to which a pointer to member refers, or the top-level function type of a function typedef declaration. The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type, i.e., it does not create a cv-qualified function type. In fact, if at any time in the determination of a type a cv-qualified function type is formed, the program is ill-formed. -----
It is not too clear whether it applies to partial template specialization, since we don't really "form" a type - we just consider a possibitity: typedef int my_const_function() const; template<typename T> struct remove_const { typedef T type; }; template<typename T> struct remove_const< T const > { typedef T type; }; // somwhere else remove_const<my_const_function>::type // ill-formed?
There might be more references, but this gives a significantly strong implication that cv-qualification on function types is radically different than normal cv-qualification.
...and that cv-qualification on function types is intended for nonstatic member functions only (at least that's the impression I get from reading that paragraph).
The cv-qualifiers are modifying the implicit 'this' parameter. I.e. the cv-qualifiers don't modify the function type (all functions are 'const' because C++ doesn't treat functions as first-class objects); they modify an implicit formal parameter. So attempting to remove cv-qualification this way would be akin to transforming 'void (const int*)' into 'void (int*)'.
I don't find it very convincing -- we're talking about two different pairs of shoes here (syntax and type system vs. semantic treatment), IMO.
struct C { };
template<class T> struct is_const_function : is_pointer_to_const_member_function<T C::*> { };
Another thought on this one: as you said already, before forming a type C::*T we have to make sure it works for the T we have. But can we do it with T actually being a type which renders our program ill-formed when encountered (and without relying on undefined behaviour)? <snip>
In this particular case it doesn't cost much. But if I'm going to do a trivial thing as finding out whether 'int' is a (any cv-qualified) function I need a second non-trivial template instantiation and a couple of trivial ones as you mentioned already. I'm not sure this feature is worth its price. Further, if your compiler is smart enough you can easily write it yourself if you need it.
Yes. On the same token, however, I can just as easily write any other sort of function type manipulation that I might need. The point is that a library like yours should prevent the need for me to do it.
Right. But is there a need for raw, cv-qualified functions in the first place?
If the feature is not used, the only possible *significant* compile-time overhead that I see is preprocessing.
Right. However, I'm not concerned about preprocessing at all (I use preprocessed files). I also don't care about parsing time (it's comparatively little and it costs once per translation unit). What counts is the complexitiy of using the metafunctions.
This can be solved by making headers more granular (not a commentary on your library) and simply not including it. If it is used, then the user pays for it with a few template instantiations--just like anything else. From an implementation point-of-view (meaning the cost on your time personally), supporting this would be fairly easy if you don't try to make it work on compilers that are fundamentally broken in this area.
I don't find your suggestion of testing C::*T instead of T generally unattractive (and ideally it might simplify things). The conditions for applying it would be: (when integrating) - be sure your suggestion builts on solid C++ (see above) - find a nice name to disambiguate const and volatile property tags so I won't need an underscore suffix (when the library is used) - it works with the compiler - the configuration allows it by specifying the same calling conventions for member and non member functions (and there is no MSVC __thiscall weirdness around)
If that is the case, then you shouldn't be supporting open
variadics.
Support for that adds significant overhead to the implementation. Granted, variadic function types are more common than cv-qualified function types, but they are still quite rare.
Can't really say 'printf' is a dark corner of the language...
The type of 'printf' may have C linkage which you can't do anything with on any conforming compiler. Basically, 'printf' is untouchable (in this context) in portable code.
Oh - I didn't mean 'printf' personally! It's just that the very first library function a C programmer usually learns has a variadic argument list, so I found it wrong to refer to open variadics as being an esoteric feature.
"Dark history", perhaps. And open variadics can be quite useful. We shouldn't make assumptions on how many people use them -- variadic functions have been there for a long time.
Trust me, I'm a big fan of the concept of variadics. Given "reasonable" language support, they are a very enabling feature for a variety of things. (This is one of the reasons why I'm glad that C is still around. IMO, C++ tends to overlook the fundamental building blocks (e.g. procedural programming) as it grows. In some sense, C keeps C++ grounded. Of course, C is not the be all and end all of procedural programming. By now, we should have nested functions, with them comes closures, and with closures comes anonymous functions (i.e. lambda functions). These are fundamental building blocks.) Unfortunately, we don't yet have reasonable variadic support in C++. We need typesafe variadic functions, variadic templates, and variadic macros.
I agree.
However right now, given that argument lists are an iterative syntactic structure (currently at odds with generic programming), that current variadic functions aren't typesafe (at odds with generic programming), and that you can't portably pass anything to them except POD's (at odds with generic programming)--it's a safe bet that function type manipulation (which would likely be done in generic code) of variadic function types will be extremely rare.
I have to annotate a tiny bit of rationale here: int func(int...) can be invoked like func(1), so it should be a valid argument for a generic facility that accepts a unary callable argument which in turn has an int parameter.
Variadic functions (specifically, how to use them even to the point of how to invoke them) are way too semantically dependent on extra-linguistic knowledge like documentation. I certainly don't think you should remove support for them--I just see its utility as on par with cv-qualified function types--yet supporting it effectively doubles all of the template specializations required.
From what I have benchmarked so far it seems that adding (partial) specializations has a noticably smaller impact on the compilation time than adding instantiations (as required for decision making and matching these specializations twice).
I don't buy the 'cost' argument as opposed to the 'completeness' argument, but I'm not terribly concerned over the lack of support. However, I'm a would-be user of a library, not the library author. If I was the library author, completeness would be a worthwhile goal in and of itself--it is a requirement for mastery of the subject. As a library author in other areas, the most annoying limitations are often those corner cases that you can do nothing about (and this isn't one of them), but present a barrior to completeness. It's the difference between "as good as can be given x, y, and z" and "ideal". My disagreement is more of a disagreement with perspective rather than over a particular feature.
Here is no disagreement at all (at least at this abstract level): I'm all for completeness but I'm not convinced that what you are proposing is in fact about completeness and not about emulating consistency where there is none. Plus I'm wondering whether it's implementable in ISO C++ at all. Thanks, Tobias

Tobias Schwinger wrote:
Paul Mensonides wrote:
----- 8.3.5/4
A cv-qualifier-seq shall only be part of the function type for a nonstatic member function, the function type to which a pointer to member refers, or the top-level function type of a function typedef declaration. The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type, i.e., it does not create a cv-qualified function type. In fact, if at any time in the determination of a type a cv-qualified function type is formed, the program is ill-formed. -----
It is not too clear whether it applies to partial template specialization, since we don't really "form" a type - we just consider a possibitity:
typedef int my_const_function() const;
template<typename T> struct remove_const { typedef T type; }; template<typename T> struct remove_const< T const > { typedef T type; };
// somwhere else remove_const<my_const_function>::type // ill-formed?
http://tinyurl.com/52g6s (item 295) is still too thin for this case, isn't it?

Tobias Schwinger wrote:
It is not too clear whether it applies to partial template specialization, since we don't really "form" a type - we just consider a possibitity:
typedef int my_const_function() const;
template<typename T> struct remove_const { typedef T type; };
template<typename T> struct remove_const< T const > { typedef T type; };
// somwhere else remove_const<my_const_function>::type // ill-formed?
Well formed, returns my_const_function. The specialization doesn't match.
http://tinyurl.com/52g6s (item 295) is still too thin for this case, isn't it?
#295 makes some previously ill-formed constructs well formed, such as typedef my_const_function const my_very_const_function; but does not affect the above example.

Peter Dimov wrote:
Tobias Schwinger wrote:
It is not too clear whether it applies to partial template specialization, since we don't really "form" a type - we just consider a possibitity:
typedef int my_const_function() const;
template<typename T> struct remove_const { typedef T type; };
template<typename T> struct remove_const< T const > { typedef T type; };
// somwhere else remove_const<my_const_function>::type // ill-formed?
Well formed, returns my_const_function.
Wasn't anywhere near obvious to me before reading #295, though...
The specialization doesn't match.
Where do I find it in the standard and/or what should happen in the following two cases? template<typename T> struct remove_member_pointer { typedef T type; }; template<typename T, typename C> struct remove_member_pointer< T C::* > { typedef T type; }; remove_member_pointer< my_const_function >::type // <-- case 1 template<typename T, typename C> struct add_member_pointer { typedef T C::*type; }; class X; add_member_pointer< my_const_function, X >::type // <-- case 2 Thanks, Tobias

Tobias Schwinger wrote: [...]
typedef int my_const_function() const;
Where do I find it in the standard and/or what should happen in the following two cases?
Don't know about the standard, but...
template<typename T> struct remove_member_pointer { typedef T type; };
template<typename T, typename C> struct remove_member_pointer< T C::* > { typedef T type; };
remove_member_pointer< my_const_function >::type // <-- case 1
The specialization doesn't match, because int () const is not of the form T C::*, so the primary template is selected and echoes my_const_function back.
template<typename T, typename C> struct add_member_pointer { typedef T C::*type; };
class X;
add_member_pointer< my_const_function, X >::type // <-- case 2
int (X::*) () const. If you pass that to remove_member_pointer, it would give you my_const_function.

Peter Dimov wrote:
Tobias Schwinger wrote:
[...]
typedef int my_const_function() const;
Where do I find it in the standard and/or what should happen in the following two cases?
Don't know about the standard, but...
template<typename T> struct remove_member_pointer { typedef T type; };
template<typename T, typename C> struct remove_member_pointer< T C::* > { typedef T type; };
remove_member_pointer< my_const_function >::type // <-- case 1
The specialization doesn't match, because int () const is not of the form T C::*, so the primary template is selected and echoes my_const_function back.
Ooops -- of course! Actually I wanted to write "my_const_mem_fun_ptr" - fortunately you applied some intuitive error correction on the fly...
template<typename T, typename C> struct add_member_pointer { typedef T C::*type; };
class X;
add_member_pointer< my_const_function, X >::type // <-- case 2
int (X::*) () const.
If you pass that to remove_member_pointer, it would give you my_const_function.
Makes sense. Would be too great if /all/ compilers behaved this way... Thanks, Tobias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Tobias Schwinger
It is not too clear whether it applies to partial template specialization, since we don't really "form" a type - we just consider a possibitity:
typedef int my_const_function() const;
template<typename T> struct remove_const { typedef T type; }; template<typename T> struct remove_const< T const > { typedef T type; };
// somwhere else remove_const<my_const_function>::type // ill-formed?
My main point in quoting the above is that "a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type. i.e., it does not create a cv-qualified function type." Syntactically, saying 'const T' where 'T' is a function type is applying cv-qualification to the whole function type--which doesn't work. The cv-qualifiers on a function type (such as 'int () const') are only an internal part of the composite expression that forms a function type. Even syntactically, a cv-qualified function type (in the sense of 'const T' could not be written 'int () const' in the C++ syntax any more than 'int [] const' can be because of the wraparound declarator syntax.
There might be more references, but this gives a
significantly strong
implication that cv-qualification on function types is radically different than normal cv-qualification.
...and that cv-qualification on function types is intended for nonstatic member functions only (at least that's the impression I get from reading that paragraph).
The *types* cannot be used to declare anything else and no composite types (except pointers-to-members) can be formed from them (e.g. you can't have a regular pointer to a cv-qualified function type, such as 'int (*)() const').
The cv-qualifiers are modifying the implicit 'this' parameter. I.e. the cv-qualifiers don't modify the function type (all functions are 'const' because C++ doesn't treat functions as first-class objects); they modify an implicit formal parameter. So attempting to remove cv-qualification this way would be akin to transforming 'void (const int*)' into 'void (int*)'.
I don't find it very convincing -- we're talking about two different pairs of shoes here (syntax and type system vs. semantic treatment), IMO.
The syntax of the language, particularly the declarator syntax has no place for cv-qualification on wraparound declarators (like function types and array types). The trailing cv-qualifiers on a function type are a syntactic special case, are interpreted in a special way in the type system, and receive special semantic treatment. I.e. all parts of it are special cases that don't follow the general rule.
struct C { };
template<class T> struct is_const_function : is_pointer_to_const_member_function<T C::*> { };
Another thought on this one: as you said already, before forming a type C::*T we have to make sure it works for the T we have. But can we do it with T actually being a type which renders our program ill-formed when encountered (and without relying on undefined behaviour)?
You'd have to specialize-out any type that can't be the subject of a pointer-to-member. E.g. references are an example: template<class T> struct is_const_function<T&> { static const bool value = false; }; There aren't that many.
Yes. On the same token, however, I can just as easily write any other sort of function type manipulation that I might need. The point is that a library like yours should prevent the need for me to do it.
Right. But is there a need for raw, cv-qualified functions in the first place?
I don't know. What is the need for manipulating pointer-to-member-function types? The immediate difference is that pointers-to-members are class specific (i.e. you have to supply the C::* part where C is some type). What if you're passing them to something but want to apply the same function type to form multiple pointers to members of different classes? I.e. template<class T, class U, class F> class abc { typename return_type<F>::type func(F A::* p, F B::* q) { // ... } }; Note that I'm just pulling this out of the magical land of make-believe where I live. I don't directly have a need for this, but its something that someone might need for some reason.
However, I'm not concerned about preprocessing at all (I use preprocessed files). I also don't care about parsing time (it's comparatively little and it costs once per translation unit). What counts is the complexitiy of using the metafunctions.
Okay.
I don't find your suggestion of testing C::*T instead of T generally unattractive (and ideally it might simplify things). The conditions for applying it would be:
(when integrating) - be sure your suggestion builts on solid C++ (see above)
It is solid C++, it just isn't implemented correctly on several major C++ compilers.
- find a nice name to disambiguate const and volatile property tags so I won't need an underscore suffix
I used to dispise them, but I've found that you get used to them fairly quickly, and they just plain more convenient than any alternatives.
(when the library is used) - it works with the compiler - the configuration allows it by specifying the same calling conventions for member and non member functions (and there is no MSVC __thiscall weirdness around)
#if !MSVC ... all related functionality ... #endif
I have to annotate a tiny bit of rationale here: int func(int...) can be invoked like func(1), so it should be a valid argument for a generic facility that accepts a unary callable argument which in turn has an int parameter.
I agree, but it's likely to be extremely rare. The entire concept of passing (e.g.) a pointer to a variadic function to a generic facility is fraught with problems.
From what I have benchmarked so far it seems that adding (partial) specializations has a noticably smaller impact on the compilation time than adding instantiations (as required for decision making and matching these specializations twice).
What do you mean by, "as required for decision making and matching these specializations twice"? What decisions (during the execution of the code) are you talking about, and why would you need to match these specializations twice?
I'm all for completeness but I'm not convinced that what you are proposing is in fact about completeness and not about emulating consistency where there is none.
It's not about emulation, its about mirroring all of the related facilities that C++ has. Cv-unqualified function types are just a subset of function types as a whole. They are a refinement that introduces more capabilities.
Plus I'm wondering whether it's implementable in ISO C++ at all.
It is, but AFAIK they can only be matched/deduced with partial specializations. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
version will pedantically use the term "function type" as defined by the standard and will not refer to a function pointer as being a function type!
That's fine with me. I only really commented to point out that there is no "member function type" as a distinct entity. I don't think that 'nonmember' is a property of a function type--it just doesn't make sense.
We're only talking about making it a property of a function _pointer_ type. -- Dave Abrahams Boost Consulting www.boost-consulting.com

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.
Please try to avoid words like "concretized", they don't really exist. Try "made concrete", folks will be able to understand it better :-) John.

Here we go again. The next update. Big thanks go to Rob Stewart and David Abrahams for their helping with this text. There is a version of this passage with markup: http://tinyurl.com/bxvke Can we freeze this part? Regards, Tobias Tag Types ---------- The Function Type library uses tag types to represent one more properties of a type, such as its variadicness or whether the function is decorated with a pointer. Tags that represent the values of a single property are called property tags. These tags can be used to determine whether one property of a type or another tag has a particular value. is_function< T, variadic > is_function< T, pointer > 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. tag<pointer,variadic> // describes a pointer to a variadic function When several tags for the same property appear in the argument list, only the last one is used; others are ignored. tag<pointer,reference> // same as 'reference' The following code creates the type int(*)(int...). function_type<mpl::vector<int,int>, tag<pointer,variadic> >::type All properties not described by the tag acquire a default. The next example creates the type of an undecorated (variadic) function of the default calling convention: int(int...). function_type<mpl::vector<int,int>, variadic >::type A compound property tag matches a type only when all of its component properties match: is_function< void(&)(...) , tag<reference,variadic> >::value // is true is_function< void(X::*)(...), tag<reference,variadic> >::value // is false

From: Tobias Schwinger <tschwinger@neoscientists.org>
Here we go again. The next update. Big thanks go to Rob Stewart and David Abrahams for their helping with this text.
You're welcome. I'm glad to help.
There is a version of this passage with markup: http://tinyurl.com/bxvke
Can we freeze this part?
I don't think it is finished yet, but it is a vast improvement over the earlier versions.
Tag Types ----------
The Function Type library uses tag types to represent one more properties of a type, such as its variadicness or whether the function is decorated with a pointer.
function type, such as whether it is variadic or is a pointer to a function. I dislike "variadicness." It just struck me that a type is never decorated with a pointer, though it can be a pointer to another type. Hence, "is a pointer to a function" rather than "decorated with a pointer."
Tags that represent the values of a single property are called property tags. These tags can be used to determine whether one property of a type or another tag has a particular value.
is_function< T, variadic > is_function< T, pointer >
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.
tag<pointer,variadic> // describes a pointer to a variadic function
When several tags for the same property appear in the argument list, only the last
I think this may have bounced around already, but "the argument list" sounds too vague to me. It should be "tag's argument list."
one is used; others are ignored.
s/others/all others/
tag<pointer,reference> // same as 'reference'
s/'reference'/tag<reference>/
The following code creates the type int(*)(int...).
function_type<mpl::vector<int,int>, tag<pointer,variadic> >::type
All properties not described by the tag acquire a default. The next example
All properties have a default tag. If you don't specify a tag for a property, that property's default tag is used instead. The following expression
creates the type of an undecorated (variadic) function of the default calling
s/ (variadic)/, variadic/ s/of the default/with the default/
convention: int(int...).
function_type<mpl::vector<int,int>, variadic >::type
Do the defaults only apply to synthesis? You only show/describe their use in that context. I haven't looked at the text with markup, but the following text seems disjoint from the foregoing:
A compound property tag matches a type only when all of its component properties match:
is_function< void(&)(...) , tag<reference,variadic> >::value // is true is_function< void(X::*)(...), tag<reference,variadic> >::value // is false
Since this example uses is_function as the earlier examples did, perhaps you could move this part ahead of "The following code creates the type int(*)(int...)" part. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Here we go again. The next update. Big thanks go to Rob Stewart and David Abrahams for their helping with this text.
You're welcome. I'm glad to help.
There is a version of this passage with markup: http://tinyurl.com/bxvke
Can we freeze this part?
I don't think it is finished yet, but it is a vast improvement over the earlier versions.
Rob, I'm sorry to say that you are using a slightly outdated version. I'll try to merge your suggestions in, though (I always post the most recent update to the "Review Result" thread). Some more things have changed (e.g. there is no decoration aspect anymore) so you might want to take a look at the more recent stuff and discussion if things seem strange to you in my reply.
Tag Types ----------
The Function Type library uses tag types to represent one more properties of a type, such as its variadicness or whether the function is decorated with a pointer.
function type, such as whether it is variadic or is a pointer to a function.
I dislike "variadicness."
It just struck me that a type is never decorated with a pointer, though it can be a pointer to another type. Hence, "is a pointer to a function" rather than "decorated with a pointer."
Seems solved. The Function Types library uses tag types to represent a type's properties, such as its calling convention or whether it is variadic.
Tags that represent the values of a single property are called property tags. These tags can be used to determine whether one property of a type or another tag has a particular value.
is_function< T, variadic > is_function< T, pointer >
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.
tag<pointer,variadic> // describes a pointer to a variadic function
When several tags for the same property appear in the argument list, only the last
I think this may have bounced around already, but "the argument list" sounds too vague to me. It should be "tag's argument list."
Hmm... We're talking about "class template tag" at this point. On second thought adding "in tag's" seems good to me, because other class templates are used in the following text.
one is used; others are ignored.
s/others/all others/
Why? I don't see it's necessary.
tag<pointer,reference> // same as 'reference'
s/'reference'/tag<reference>/
It won't work, since the unary version of tag is an artefact I overlooked updating the synopsis (shame on me). Further, this example will be thrown out, anyway.
The following code creates the type int(*)(int...).
function_type<mpl::vector<int,int>, tag<pointer,variadic> >::type
All properties not described by the tag acquire a default. The next example
All properties have a default tag. If you don't specify a tag for a property, that property's default tag is used instead. The following expression
There are no "default tags" - there is a default value, but the "default tags" (which used to be the fully general "abstract" ones) have been removed from the interface). With this issue adjusted your suggestion might be OK. However, I don't see why it should be better: It uses more words to essentially say the same thing and seems to be cut-off from the previous example (it shouldn't). Further I'm pretty sure I'ld personally prefer the original being the reader (but that's perhaps just me).
creates the type of an undecorated (variadic) function of the default calling
s/ (variadic)/, variadic/
"Variadic" is in parentheses to denote that it doesn't make up the point here. s/(variadic)// # but I'm not sure
s/of the default/with the default/
OK.
convention: int(int...).
function_type<mpl::vector<int,int>, variadic >::type
Do the defaults only apply to synthesis?
Well, sort of.
You only show/describe their use in that context.
?! I thought that's what I do. This paragraph (and the previous two or so) about using tags in terms of synthesis...
I haven't looked at the text with markup, but the following text seems disjoint from the foregoing:
Yeah, because we shift to classification here.
A compound property tag matches a type only when all of its component properties match:
is_function< void(&)(...) , tag<reference,variadic> >::value // is true is_function< void(X::*)(...), tag<reference,variadic> >::value // is false
Since this example uses is_function as the earlier examples did, perhaps you could move this part ahead of "The following code creates the type int(*)(int...)" part.
OK. Things read smoother this way. Thanks, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
I'm sorry to say that you are using a slightly outdated version. I'll try to merge your suggestions in, though (I always post the most recent update to the "Review Result" thread).
Shortly after posting, I found the new thread. Oh well.
Some more things have changed (e.g. there is no decoration aspect anymore) so you might want to take a look at the more recent stuff and discussion if things seem strange to you in my reply.
I've been reading that thread. Thanks for the heads up.
The Function Type library uses tag types to represent one more properties of a type, such as its variadicness or whether the function is decorated with a pointer.
function type, such as whether it is variadic or is a pointer to a function.
I dislike "variadicness."
It just struck me that a type is never decorated with a pointer, though it can be a pointer to another type. Hence, "is a pointer to a function" rather than "decorated with a pointer."
Seems solved.
The Function Types library uses tag types to represent a type's properties, such as its calling convention or whether it is variadic.
Yep, although ISTR some remaining reference to a function type being "decorated with a pointer." Be on the lookout for that phrasing in your new version.
Tags that represent the values of a single property are called property tags. These tags can be used to determine whether one property of a type or another tag has a particular value.
is_function< T, variadic > is_function< T, pointer >
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.
tag<pointer,variadic> // describes a pointer to a variadic function
When several tags for the same property appear in the argument list, only the last
I think this may have bounced around already, but "the argument list" sounds too vague to me. It should be "tag's argument list."
Hmm... We're talking about "class template tag" at this point. On second thought adding "in tag's" seems good to me, because other class templates are used in the following text.
It's not just that. There's already been mention of is_function, for example. The change just ensures that the reader is thinking about tag's template argument list.
one is used; others are ignored.
s/others/all others/
Why? I don't see it's necessary.
"Others are ignored," even if it was taken from an earlier suggestion of mine, sounds a bit abrupt. Adding "all" makes it sound better. (It isn't needed for clarity, just readability.)
tag<pointer,reference> // same as 'reference'
s/'reference'/tag<reference>/
It won't work, since the unary version of tag is an artefact I overlooked updating the synopsis (shame on me). Further, this example will be thrown out, anyway.
OK. I see.
The following code creates the type int(*)(int...).
function_type<mpl::vector<int,int>, tag<pointer,variadic> >::type
All properties not described by the tag acquire a default. The next example
All properties have a default tag. If you don't specify a tag for a property, that property's default tag is used instead. The following expression
There are no "default tags" - there is a default value, but the "default tags" (which used to be the fully general "abstract" ones) have been removed from the interface).
With this issue adjusted your suggestion might be OK. However, I don't see why it should be better: It uses more words to essentially say the same thing and seems to be cut-off from the previous example (it shouldn't). Further I'm pretty sure I'ld personally prefer the original being the reader (but that's perhaps just me).
A property cannot acquire anything; "acquire" is a transitive verb. It has things that define it, but it cannot add to those things. Hence my phrasing: "properties have a default."
creates the type of an undecorated (variadic) function of the default calling
s/ (variadic)/, variadic/
"Variadic" is in parentheses to denote that it doesn't make up the point here.
s/(variadic)// # but I'm not sure
As written, the text suggests the possibility of "function/variadic function." The example creates a variadic function type, right? Therefore, "variadic" shouldn't be in parentheses.
convention: int(int...).
function_type<mpl::vector<int,int>, variadic >::type
Do the defaults only apply to synthesis?
Well, sort of.
You only show/describe their use in that context.
?! I thought that's what I do. This paragraph (and the previous two or so) about using tags in terms of synthesis...
But the section is about properties plus their defaults, not about type synthesis, right? Did I miss/forget you discussing defaults in the context of classification? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
Yep, although ISTR some remaining reference to a function type being "decorated with a pointer." Be on the lookout for that phrasing in your new version.
The term should be OK, I figure. Since the Overview section starts with this text: 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. [... explains what this means in other words and gives examples] I'll try to post a preview soon.
Tags that represent the values of a single property are called property tags. These tags can be used to determine whether one property of a type or another tag has a particular value.
is_function< T, variadic > is_function< T, pointer >
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.
tag<pointer,variadic> // describes a pointer to a variadic function
When several tags for the same property appear in the argument list, only the last
I think this may have bounced around already, but "the argument list" sounds too vague to me. It should be "tag's argument list."
Hmm... We're talking about "class template tag" at this point. On second thought adding "in tag's" seems good to me, because other class templates are used in the following text.
It's not just that. There's already been mention of is_function, for example. The change just ensures that the reader is thinking about tag's template argument list.
OK. "in tag's"'s in already ;-).
one is used; others are ignored.
s/others/all others/
Why? I don't see it's necessary.
"Others are ignored," even if it was taken from an earlier suggestion of mine, sounds a bit abrupt. Adding "all" makes it sound better. (It isn't needed for clarity, just readability.)
OK.
The following code creates the type int(*)(int...).
function_type<mpl::vector<int,int>, tag<pointer,variadic> >::type
All properties not described by the tag acquire a default. The next example
All properties have a default tag. If you don't specify a tag for a property, that property's default tag is used instead. The following expression
There are no "default tags" - there is a default value, but the "default tags" (which used to be the fully general "abstract" ones) have been removed from the interface).
With this issue adjusted your suggestion might be OK. However, I don't see why it should be better: It uses more words to essentially say the same thing and seems to be cut-off from the previous example (it shouldn't). Further I'm pretty sure I'ld personally prefer the original being the reader (but that's perhaps just me).
A property cannot acquire anything; "acquire" is a transitive verb. It has things that define it, but it cannot add to those things. Hence my phrasing: "properties have a default."
I'm not sure I understand you correctly. The default is a function -- not a constant. I don't believe "have a default" is entirely correct here. The property acquires (even if it may not work English-wise ;-) ) a value based on the context the tag is used in (and I believe explaining this doesn't really help the user, who only needs to know "there's a default behaviour by definition - I gotta look it up").
creates the type of an undecorated (variadic) function of the default calling
s/ (variadic)/, variadic/
"Variadic" is in parentheses to denote that it doesn't make up the point here.
s/(variadic)// # but I'm not sure
As written, the text suggests the possibility of "function/variadic function." The example creates a variadic function type, right? Therefore, "variadic" shouldn't be in parentheses.
The examples just specifies one property tag (which has nothing to do with what I'm trying to show -- but I can't show it not specifying a tag at all, because of the default argument -- which btw. is consistent with the rest but defaulting is nothing special for a default argument) so the text can tell the other property defaults.
convention: int(int...).
function_type<mpl::vector<int,int>, variadic >::type
Do the defaults only apply to synthesis?
Well, sort of.
You only show/describe their use in that context.
?! I thought that's what I do. This paragraph (and the previous two or so) about using tags in terms of synthesis...
But the section is about properties plus their defaults, not about type synthesis, right?
/These/ defaults only apply to synthesis. It doesn't have to be spelled out because....
Did I miss/forget you discussing defaults in the context of classification?
"A compound property tag matches a type only when all of its component properties match". Well, this tells you what it means not to specify a property for classification, doesn't it? s/only/if and only if/? Thanks, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
Yep, although ISTR some remaining reference to a function type being "decorated with a pointer." Be on the lookout for that phrasing in your new version.
The term should be OK, I figure. Since the Overview section starts with this text:
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.
Maybe I'm being too picky, but a pointer doesn't decorate a function type. You can have a pointer to a function, which has type pointer to function, but a pointer, which is a variable holding an address (ignoring pointers to member functions) can't decorate a type. Note that a function type can be decorated--to use your term--to *form* a pointer to function, for example.
The following code creates the type int(*)(int...).
function_type<mpl::vector<int,int>, tag<pointer,variadic> >::type
All properties not described by the tag acquire a default. The next example
All properties have a default tag. If you don't specify a tag for a property, that property's default tag is used instead. The following expression
There are no "default tags" - there is a default value, but the "default tags" (which used to be the fully general "abstract" ones) have been removed from the interface).
With this issue adjusted your suggestion might be OK. However, I don't see why it should be better: It uses more words to essentially say the same thing and seems to be cut-off from the previous example (it shouldn't). Further I'm pretty sure I'ld personally prefer the original being the reader (but that's perhaps just me).
A property cannot acquire anything; "acquire" is a transitive verb. It has things that define it, but it cannot add to those things. Hence my phrasing: "properties have a default."
I'm not sure I understand you correctly.
The default is a function -- not a constant. I don't believe "have a default" is entirely correct here.
The property acquires (even if it may not work English-wise ;-) ) a value based on the context the tag is used in (and I believe explaining this doesn't really help the user, who only needs to know "there's a default behaviour by definition - I gotta look it up").
I think I see what you're trying to say. Perhaps the right wording is that "a default value is used for a missing property when synthesizing a type," or something along those lines.
creates the type of an undecorated (variadic) function of the default calling
s/ (variadic)/, variadic/
"Variadic" is in parentheses to denote that it doesn't make up the point here.
s/(variadic)// # but I'm not sure
As written, the text suggests the possibility of "function/variadic function." The example creates a variadic function type, right? Therefore, "variadic" shouldn't be in parentheses.
The examples just specifies one property tag (which has nothing to do with what I'm trying to show -- but I can't show it not specifying a tag at all, because of the default argument -- which btw. is consistent with the rest but defaulting is nothing special for a default argument) so the text can tell the other property defaults.
I see. How about, "creates the type of an undecorated function (variadic in this case) of the default...."
convention: int(int...).
function_type<mpl::vector<int,int>, variadic >::type
Do the defaults only apply to synthesis?
Well, sort of.
You only show/describe their use in that context.
?! I thought that's what I do. This paragraph (and the previous two or so) about using tags in terms of synthesis...
But the section is about properties plus their defaults, not about type synthesis, right?
/These/ defaults only apply to synthesis. It doesn't have to be spelled out because....
Did I miss/forget you discussing defaults in the context of classification?
"A compound property tag matches a type only when all of its component properties match". Well, this tells you what it means not to specify a property for classification, doesn't it?
That tells me an omitted component property is ignored when making the match. There is no need for the concept of a default in that context, right? Consequently, defaults only apply to synthesis and, therefore, what you had should be fine.
s/only/if and only if/?
Not necessary. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
Yep, although ISTR some remaining reference to a function type being "decorated with a pointer." Be on the lookout for that phrasing in your new version.
The term should be OK, I figure. Since the Overview section starts with this text:
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.
Maybe I'm being too picky, but a pointer doesn't decorate a function type. You can have a pointer to a function, which has type pointer to function, but a pointer, which is a variable holding an address (ignoring pointers to member functions) can't decorate a type.
In fact, that's probably not too bad of a point...
Note that a function type can be decorated--to use your term--to *form* a pointer to function, for example.
Being picky I guess you meant "a pointer to function *type*" - otherwise "form" should be "declare" ;-). ...and other compound types, such as function pointer, function reference and member function types. I believe I can get rid of that term in the rest of the text as well.
The following code creates the type int(*)(int...).
function_type<mpl::vector<int,int>, tag<pointer,variadic> >::type
All properties not described by the tag acquire a default. The next example
All properties have a default tag. If you don't specify a tag for a property, that property's default tag is used instead. The following expression
There are no "default tags" - there is a default value, but the "default tags" (which used to be the fully general "abstract" ones) have been removed from the interface).
With this issue adjusted your suggestion might be OK. However, I don't see why it should be better: It uses more words to essentially say the same thing and seems to be cut-off from the previous example (it shouldn't). Further I'm pretty sure I'ld personally prefer the original being the reader (but that's perhaps just me).
A property cannot acquire anything; "acquire" is a transitive verb. It has things that define it, but it cannot add to those things. Hence my phrasing: "properties have a default."
I'm not sure I understand you correctly.
The default is a function -- not a constant. I don't believe "have a default" is entirely correct here.
The property acquires (even if it may not work English-wise ;-) ) a value based on the context the tag is used in (and I believe explaining this doesn't really help the user, who only needs to know "there's a default behaviour by definition - I gotta look it up").
I think I see what you're trying to say. Perhaps the right wording is that "a default value is used for a missing property when synthesizing a type," or something along those lines.
Something along those lines. How's Default values are selected for properties not specified by the tag here (see <somewhere else>). ?
creates the type of an undecorated (variadic) function of the default calling
s/ (variadic)/, variadic/
"Variadic" is in parentheses to denote that it doesn't make up the point here.
s/(variadic)// # but I'm not sure
As written, the text suggests the possibility of "function/variadic function." The example creates a variadic function type, right? Therefore, "variadic" shouldn't be in parentheses.
The examples just specifies one property tag (which has nothing to do with what I'm trying to show -- but I can't show it not specifying a tag at all, because of the default argument -- which btw. is consistent with the rest but defaulting is nothing special for a default argument) so the text can tell the other property defaults.
I see. How about, "creates the type of an undecorated function (variadic in this case) of the default...."
OK. Let's get rid of the "decorate" artefact: ...creates the type of a function (variadic in this case) of the default... Thanks, Tobias

From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
From: Tobias Schwinger <tschwinger@neoscientists.org>
Rob Stewart wrote:
Note that a function type can be decorated--to use your term--to *form* a pointer to function, for example.
Being picky I guess you meant "a pointer to function *type*" - otherwise "form" should be "declare" ;-).
Indeed.
...and other compound types, such as function pointer, function reference and member function types.
I believe I can get rid of that term in the rest of the text as well.
Cool.
I think I see what you're trying to say. Perhaps the right wording is that "a default value is used for a missing property when synthesizing a type," or something along those lines.
Something along those lines. How's
Default values are selected for properties not specified by the tag here (see <somewhere else>).
?
Oh, sorry. I guess I missed replying to that. I like "are selected," particularly if you avoid the passive voice. That is, say what is doing the selecting.
I see. How about, "creates the type of an undecorated function (variadic in this case) of the default...."
OK. Let's get rid of the "decorate" artefact:
...creates the type of a function (variadic in this case) of the default...
Good. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

On Wed, 22 Jun 2005 14:30:24 +0200 Tobias Schwinger <tschwinger@neoscientists.org> wrote: I've been on vacation, and I return to see tons of comments about function types. Instead of reading through all the replies (looks to be over 100 of them), I'd first like to see the document as a result of all the comments and your changes, if it is available. Thanks!

Jody Hagins wrote:
On Wed, 22 Jun 2005 14:30:24 +0200 Tobias Schwinger <tschwinger@neoscientists.org> wrote:
I've been on vacation, and I return to see tons of comments about function types. Instead of reading through all the replies (looks to be over 100 of them), I'd first like to see the document as a result of all the comments and your changes, if it is available.
The following posts are the latest summarizing ones: Todo list: http://lists.boost.org/boost/2005/06/29005.php Synopsis: http://lists.boost.org/boost/2005/07/29657.php New tags: http://lists.boost.org/boost/2005/07/29659.php I usually post links to the updates to the "Review Result" thread. http://lists.boost.org/boost/2005/06/29473.php Regards, Tobias

Synopsis: --------- namespace boost { namespace function_type { // Result: bool, Concept: MPL-Integral Constant template<typename T, typename QueryTag = undecorated> struct is_function_; // Result: bool, Concept: MPL-Integral Constant template<typename T> struct is_function_pointer; template<typename T> struct is_function_reference; template<typename T> struct is_member_function_pointer_; // Concept: Tag template<typename T> struct kind_of<T>; // Result: bool, Concept: MPL-Integral Constant template<typename Tag1_or_Signature, typename QueryTag> struct represents; // Result: bool, Concept: MPL-Integral Constant template<typename T> struct arity<T>; // Result: type, Concept: Metafunction template<typename T, typename Index> struct parameter; template<typename T, std::size_t Index> struct parameter_c; // Result: type, Concept: Metafunction template<typename T> struct class_of; // Result: type, Concept: Metafunction template<typename T> struct result; // Result: type, Concept: Metafunction template<typename T, typename Index> struct effective_parameter; template<typename T, std::size_t Index> struct effective_parameter_c; // Concept: MPL Random-Access Sequence template<typename T> struct parameters; // Concept: MPL Random-Access Sequence template<typename T, typename ClassT = add_reference<_> > struct effective_parameters; // Concept: MPL Extensible/Random-Access Sequence template<typename T, typename ClassT = add_reference<_> > struct signature; // Result: type, Concept: Metafunction template<typename T_or_Signature_or_Seq ,typename Tag = undecorated, typename ClassT = add_reference<_> > struct function_type; // Concept: Tag template<typename Tag1_or_Signature, typename Tag2 = ... struct tag; // Aspect tags // - decoration aspect typedef /.../ unspecified_decoration; // (*) (default) typedef /.../ unbound; // (*) (matches the next three) typedef /.../ undecorated; typedef /.../ pointer; typedef /.../ reference; typedef /.../ member_pointer; // (*) abstract - same as 'undecorated' when used for synthesis // - variadic aspect typedef /.../ unspecified_variadic; // (*) (default) typedef /.../ non_variadic; typedef /.../ variadic; // (*) abstract - same as 'non_variadic' when used for synthesis // - const aspect typedef /.../ unspecified_constness; // (*) (default) typedef /.../ const_; typedef /.../ non_const; // (*) abstract - same qualfication as the class type when used for synthesis // - volatile aspect typedef /.../ unspecified_volatility; // (*) (default) typedef /.../ volatile_; typedef /.../ non_volatile; // (*) abstract - same qualfication as the class type when used for synthesis // Calling convention aspect typedef /.../ unspecified_call; // (*) (default) typedef /.../ cdecl, stdcall, etc. (depends on configuration) // (*) abstract - uses the default calling convention when used for synthesis } }

Synopsis:
Mostly look good to me!
namespace boost { namespace function_type { // Result: bool, Concept: MPL-Integral Constant template<typename T, typename QueryTag = undecorated> struct is_function_;
I don't like the trailing underscore much, but I see why it's there :-) On the other hand, since we're in a separate namespace from type_traits we could just drop the underscore... might lead to confusion though. Come to that having the underscore will lead to confusion as well IMO. I understand why you dropped the trailing "_type" suffix, but "is_function_type" was the only obvious alternative I could think of. Hmmm, how about "is_function_kind" ? Not pretty, but it kind of sums up what the meta-function does. Any other ideas anyone?
// Result: bool, Concept: MPL-Integral Constant template<typename T> struct is_function_pointer; template<typename T> struct is_function_reference; template<typename T> struct is_member_function_pointer_;
I think the trailing underscore has to go from there as well IMO. Ideally this one and the type traits one should be the same template. They have the same semantics don't they? While we're at it, can the traits inherit from boost::integral_constant<bool, true/false> please? They will still be MPL friendly, and they'll follow the type_traits and TR1 conceptual framework as well then. The rest of the synopsis looks good to me. John.

John Maddock wrote:
Synopsis:
Mostly look good to me!
namespace boost { namespace function_type { // Result: bool, Concept: MPL-Integral Constant template<typename T, typename QueryTag = undecorated> struct is_function_;
I don't like the trailing underscore much, but I see why it's there :-)
Me not either ;-).
On the other hand, since we're in a separate namespace from type_traits we could just drop the underscore... might lead to confusion though. Come to that having the underscore will lead to confusion as well IMO.
I understand why you dropped the trailing "_type" suffix, but "is_function_type" was the only obvious alternative I could think of.
Hmmm, how about "is_function_kind" ? Not pretty, but it kind of sums up what the meta-function does.
'is_function_of_kind' perhaps -- see below.
Any other ideas anyone?
Let's just drop the underscore -- see below. Btw. the cv tags will imply 'member_pointer' decoration, so I can call them 'const_member' and 'volatile_member' instead of 'const_' and 'volatile_' respectively. No trailing underscores left then...
// Result: bool, Concept: MPL-Integral Constant template<typename T> struct is_function_pointer; template<typename T> struct is_function_reference; template<typename T> struct is_member_function_pointer_;
I think the trailing underscore has to go from there as well IMO. Ideally this one and the type traits one should be the same template. They have the same semantics don't they?
They have the same semantics, except is_function which /defaults/ to it. If this is a problem we can split off 'is_function_of_kind<T,Tag>' from 'is_function<T>'. The long-term plan is to make 'is_function' and 'is_member_function_pointer' the same templates as in Type Traits -- and since this may depend on the compiler, having no underscore has this advantage: // inside type_traits #if FUNCTION_TYPE_SUPPORTS_CURRENT_COMPILER using ::boost::function_type::$name; #else // highly portable implementation of $name #endif
While we're at it, can the traits inherit from boost::integral_constant<bool, true/false> please? They will still be MPL friendly, and they'll follow the type_traits and TR1 conceptual framework as well then
Sure. I'll generate similar code as type_traits/detail/bool_trait_def.hpp does.
The rest of the synopsis looks good to me.
Thanks, Tobias

Tobias Schwinger wrote:
John Maddock wrote:
// Result: bool, Concept: MPL-Integral Constant template<typename T> struct is_function_pointer; template<typename T> struct is_function_reference; template<typename T> struct is_member_function_pointer_;
I think the trailing underscore has to go from there as well IMO. Ideally this one and the type traits one should be the same template. They have the same semantics don't they?
They have the same semantics, except is_function which /defaults/ to it. If this is a problem we can split off 'is_function_of_kind<T,Tag>' from 'is_function<T>'. ^^^^^^^^^^^^^^
Is it?
participants (8)
-
David Abrahams
-
Jody Hagins
-
John Maddock
-
Jonathan Wakely
-
Paul Mensonides
-
Peter Dimov
-
Rob Stewart
-
Tobias Schwinger