Function Types Review Begins Monday, November 6, 2006

The function-types "fast track" review begins monday, November 6, 2006. Author ------------------------------------------- Tobias Schwinger tschwinger AT neoscientists DOT org Download ------------------------------------------- http://tinyurl.com/qaf5f Introduction -------------------------------------------- Boost.FunctionTypes provides functionality to classify, decompose and synthesize function, function pointer, function reference and pointer to member function types. In other words, the library can be used to: - test whether a type is a specific callable builtin type, - extract all component properties from callable builtin types, and - create callable builtin types from specified properties. The library is designed to work well with other Boost libraries and uses well-accepted concepts introduced by Boost and TR1. Templates that encapsulate boolean or numeric properties define a static member constant called value. Examples ---------------------------------------------- is_function_pointer< bool(*)(int) >::value // == true function_arity< bool(*)(int) >::value // == 1 Templates that encapsulate properties that are single types contain a type member called type. function_type< mpl::vector<bool,int> >::type // is bool(int) result_type< bool(&)(int) >::type // is int Templates that encapsulate properties that are type lists model an MPL-compatible type sequence. parameter_types< bool(int) > // models an MPL sequence Whats New ------------------------------------------------------------------- (from the last "official" version) - The interface, - the documentation, - the test-suite, - carefully picked and inline-documented source code examples, - code generator for preprocessed files is entirely written on top of Wave, - preprocessed files and the configuration (up to a certain extent) are compiler-agnostic, - preprocessed files do not have to be regenerated for custom configurations, unless for optimization (and changing the library code, of course), and - library is default calling convention-agnostic, OIW the default calling convention can be changed and detected without changing the library's configuration (unless for MSVC<8 due to the lack of a 'thiscall' keyword) Review Manager Comments ----------------------------------------------------- The convention is for this type of review to take at least 5 days. Of course, I'll extend it futher if there are going to be some late reviews, so let me know what you think your time frame is for submiting a review. I'll wait for you. The library was reviewed last year and has been modified to meet the concerns that were raised at that time. The previous review manager felt that another full-review was not necessary, but a shortended fast-track review was needed to address the following concerns: 1) improved docuentation is needed 2) lack of a motivating example 3) better examples in general 4) improved test-suite Please take another look at this library and express your views as to whether you think that the library is now ready for inclusion into boost. The usual critera applies. Thanks to the library author for his submission. Thanks in advance to the reviewers for submitting their reviews. Your opinions matter. Help improve this library even further by giving the author some additional feeback. Review Manager, Tom Brinkman

The function-types "fast track" review begins monday, November 6, 2006.
Author -------------------------------------------
Tobias Schwinger tschwinger AT neoscientists DOT org
Download ------------------------------------------- http://tinyurl.com/qaf5f
This link does not work for me. Regards Hartmut

"Tom Brinkman" <reportbase@gmail.com> wrote in message news:30f04db60611041254n3bf7eed9lb684344721bdb819@mail.gmail.com... Some quick impressions re function_types: function types initial thoughts Examples VC7.1 tested. Several examples don't compile. Get these messages below------->.(Other examples compile ok. OTOH is result_of_example not actually just a test?) Also get following warning Not sure if its from function types lib or cl: ATTENTION: /Gd /Gr /Gz compiler options will not ATTENTION: work with this configuration. Seeing as I have no choice other than to select one of these... I am amused. Hopefully will have more to say and do a proper review soon too. regards Andy Little //----------------------------- Compiling... fast_mem_fn_example.cpp ATTENTION: /Gd /Gr /Gz compiler options will not ATTENTION: work with this configuration. c:\boost\include\boost-1_34_0\libs\function_types\example\fast_mem_fn_example.cpp(104) : error C2975: 'Callee' : invalid template argument for 'example::fast_mem_fn_maker<MFPT>::make_fast_mem_fn', compile-time evaluatable constant expression expected with [ MFPT=int (test::* )(void) const ] c:\boost\include\boost-1_34_0\libs\function_types\example\fast_mem_fn.hpp(110) : see declaration of 'Callee' //---------------------------- Compiling... interface_example.cpp ATTENTION: /Gd /Gr /Gz compiler options will not ATTENTION: work with this configuration. c:\boost\include\boost-1_34_0\libs\function_types\example\interface_example.cpp(19) : error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'boost::function_types::function_pointer<Types>::type' with [ Types=example::concat_view<interface_x::vtable::inf2<>::result,boost::mpl::transform_view<interface_x::vtable::inf2<>::params,example::param_type<boost::mpl::_>>> ] None of the functions with this name in scope match the target type c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xlocnum(806) : while compiling class-template static data member 'const interface_x::vtable interface_x::vtable_holder<T>::val_vtable' with [ T=a_class ] c:\boost\include\boost-1_34_0\libs\function_types\example\interface_example.cpp(19) : see reference to class template instantiation 'interface_x::vtable_holder<T>' being compiled with [ T=a_class ] c:\boost\include\boost-1_34_0\libs\function_types\example\interface_example.cpp(69) : see reference to function template instantiation 'interface_x::interface_x<a_class>(T &)' being compiled with [ T=a_class ] c:\boost\include\boost-1_34_0\libs\function_types\example\interface_example.cpp(19) : error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'boost::function_types::function_pointer<Types>::type' with [ Types=example::concat_view<interface_x::vtable::inf2<>::result,boost::mpl::transform_view<interface_x::vtable::inf2<>::params,example::param_type<boost::mpl::_>>> ] None of the functions with this name in scope match the target type c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xlocnum(806) : while compiling class-template static data member 'const interface_x::vtable interface_x::vtable_holder<T>::val_vtable' with [ T=another_class ] c:\boost\include\boost-1_34_0\libs\function_types\example\interface_example.cpp(19) : see reference to class template instantiation 'interface_x::vtable_holder<T>' being compiled with [ T=another_class ] c:\boost\include\boost-1_34_0\libs\function_types\example\interface_example.cpp(74) : see reference to function template instantiation 'interface_x::interface_x<another_class>(T &)' being compiled with [ T=another_class ] Build log was saved at "file://d:\Projects\Test\Debug\BuildLog.htm" Test - 2 error(s), 0 warning(s) ---------------------- Done ---------------------- Build: 0 succeeded, 1 failed, 0 skipped //----------------------------

Andy Little wrote:
VC7.1 tested. Several examples don't compile. Get these messages below------->.
I'm aware of that. You need VC8 to see all examples compile (I think it's a very bad idea to clutter examples with workarounds, BTW).
(Other examples compile ok. OTOH is result_of_example not actually just a test?)
Well, yes and no. It's the "official" Boost.ResultOf test modified to use the reimplementation, which is an example of FunctionTypes. All examples are also built by the 'test' Jamfile to (in case of Boost-acceptance) have them show up in the regression matrix. This way, a user can see whether a particular example is supposed to compile with a certain compiler or not.
Also get following warning Not sure if its from function types lib or cl:
ATTENTION: /Gd /Gr /Gz compiler options will not ATTENTION: work with this configuration.
Seeing as I have no choice other than to select one of these... I am amused.
Good point. This message should be changed to state a) that the current configuration won't work with these compiler options, b) how to suppress the message, and c) that you should reconfigure the library if you intend to use these compiler options. Thanks for pointing me at it. Regards, Tobias

"Tobias Schwinger" <tschwinger@neoscientists.org> wrote in message news:eivn9c$s4s$1@sea.gmane.org...
Andy Little wrote:
VC7.1 tested. Several examples don't compile. Get these messages below------->.
I'm aware of that. You need VC8 to see all examples compile (I think it's a very bad idea to clutter examples with workarounds, BTW).
I see. Personally I prefer running examples to reading them, but whatever.. Might it not be a good idea to resite the documentation for the examples in the documentation, and provide a note to the effect that they will only compile on one compiler? regards Andy Little

Andy Little wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote in message news:eivn9c$s4s$1@sea.gmane.org...
Andy Little wrote:
VC7.1 tested. Several examples don't compile. Get these messages below------->.
I'm aware of that. You need VC8 to see all examples compile (I think it's a very bad idea to clutter examples with workarounds, BTW).
I see. Personally I prefer running examples to reading them, but whatever.. Might it not be a good idea to resite the documentation for the examples in the documentation, and provide a note to the effect that they will only compile on one compiler?
Honestly, I can't enumerate all the compilers capable of handling the code. What makes you assume it's only one?!

In introduction its says you can: "create callable builtin types from specified properties" This sounds cool, but what does it mean? I have visions of a user being able to create runtime functions via a script and inject them into the app at runtime. Is there an example? What's a callable builtin type? regards Andy Little

Andy Little wrote:
In introduction its says you can:
"create callable builtin types from specified properties"
Probably it's missing a comma between "callable" and "builtin" and maybe the spelling is "built-in" instead of "builtin".
This sounds cool, but what does it mean? I have visions of a user being able to create runtime functions via a script and inject them into the app at runtime.
I kinda know the problem: I have visions of pizza when someone says "anchovy" ;-).
Is there an example?
Yes, I think so - on the same page, further below.
What's a callable builtin type?
"A callable, built-in type" type that doesn not need overloaded operators for its entities to be callable (I'm using "entity" instead of "object" here to avoid inconsistencies with standard terminology). I thought this term would define itself from the context, but I might have been wrong. Regards, Tobias

I've spent some time this afternoon reviewing the contents of the function type library as its functionality is something I feel is currently missing from Boost and would like to see added. Although most of my comments are negative, I like this library, and would like to see it in Boost. I would prefer to see some modifications made first, but even in the absense of these, I'd still like to see it added. There were several different links posted; I'm assuming that <http://tinyurl.com/qaf5f> is the correct one. Throughout these comments, I am assuming the namespace alias namespace bft = boost::function_types; 1. Namespace The public interface to this library is in the boost::function_types namespace. As a propsective user of the library, it feels very much like an extension to the type_traits library, and that leaves me wondering why the library isn't in the main boost namespace with the other type_traits functionality. 2. Use of Tags After a second glance, it's clear that one reason for having separate namespaces is to avoid name collisions -- we already have a boost::is_function, for example. And this leaves me wondering how boost::is_function differs from bft::is_function as the names fail to convey the distinction. So far as I can see, the additional Tag template parameter is the only difference, and only three of the possible property tags are meaningful: variadic, non_variadic and default_cc. The majority of the time I can't imagine myself making much use of any of these tags. Are they really worth while? The 'Rationale' section of the documentation addresses this and considers some alternatives: | The first one is just using more templates so every | property has to be asked for explicitly. This approach | results in more complicated client code if more than one | propery has to be checked and in a exponentially larger | library interface. | | The second alternative is having the client pass in bit | patterns via non-type template parameters. The logic has | to be performed by the client and there are much more | error conditions. Further, class templates with non-type | template parameters do not work within MPL lambda | expressions and can cause problems with older compilers. What about the third possibility: leave it up to the client to sythesise these more complicated examples. It will involve adding a few more templates: notably is_variadic and is_default_cc. Then, instead of writing bft::is_function< T, bft::variadic >::value you would write boost:is_function<T>::value && boost::is_variadic<T>::value ... which is not significantly more verbose. I think this would be my prefered interface as it would avoid the duplication of functionality between the type_traits library (and the potential for confusion that this would cause). 3. Extensibility The internal bitmask implementation underlying the property tags does not appear to allow extension by a user. For example, there is a default_cc tag; suppose I want to add support for querying the some other calling convention. Can I write a fastcall_cc tag? Scanning through the implementation it would appear not -- certainly there's no documentation on how to do so. If a tag-like syntax is considered desireable, wouldn't something like template < typename T, template <typename> class UnaryTypeTrait > struct is_function : integral_constant< bool, is_function<T>::value && UnaryTypeTrait<T>::value > {}; be more extensible? Or does this have to work with compilers that can't handle template template parameters? 4. Naming It seems unlikely that the default_cc tag will be particularly heavily used. Given this, why not give it a more meaningful name: default_calling_convention perhaps? 5. Extern "C" linkage What should this print? extern "C" { typedef int fn(); } int main() { std::cout << bfs::is_function<fn, bfs::default_cc>::value << std::endl; } As function types differing only by language linkage are distinct types (7.4/1) (even though many compilers don't respect this), they can, in principle, have differing calling conventions, in which case the extern "C" calling convention is not default. This may be a non-issue as I don't know whether any of the compilers that Boost targets actually take advantage of this, and even if they do, I don't even know whether it is possible to detect "C" language linkage with template metaprogramming (mostly because you can't put extern "C" within a template or atemplate within an extern "C" block). 6. What is a 'callable builtin'? So far as I can see, the C++ Standard does not define 'callable', so I asume that the pertinent definition is the one in TR1, 3.1/6: | A /callable type/ is a pointer to function, a pointer to | member function, a pointer to member data, or a class | type whose objects can appear immediately to the left of | a function call operator. By this definition, function types are not callable, nor are references to functions, bizarre as this may seem. I can't find any definition of 'builtin' in either the Standard or TR1, though it is occasionally used in the Standard to refer to integral or arithmetic types -- clearly this isn't what's meant here, though! It would appear that in this context 'callable builtin' is supposed to include function types, pointers or references to function types and pointers to member functions. It does not include classes with an overloaded operator() (unsurpisingly -- it would be a very strange definition of 'builtin' that included them); nor does it include pointers to member data, even though they are 'callable' per TR1 and are seemingly as 'builtin' as pointers to member functions. Though I'm not wholly convinced with TR1's definition of 'callable', this is as close as it gets to a standard definition, and it would seem wise to make pointers to member data return true. I also think 'builtin' needs documenting even if only superficially; to me 'builtin' is a synonym to 'fundamental', though there are no callable fundamental types. 7. What is a 'callable scalar'? The term 'scalar' is defined in 3.9/10: | Arithmentic types, enumeration types, pointer types, and | pointer to member types, and cv-qualified versions of | these types are collectively called scalar types. Note that references, whether to functions or otherwise, are *not* scalars. The is_callable_scalar metafunction returns true for references to functions. This is wrong. Also, why is is_callable_scalar useful? I'm not sure I can think of a use case; and if I could, I imagine it would be rare enough that it wouldn't be much of an inconvenience to sythesise it from is_function and is_callable_builtin. 8. 'Tag Types' documentation In several places, the 'Tag Types' documentation incorrectly gives types two leading underscores. 9. Extending result_type Perhaps this is beyond the intended scope of the library, but I think it would be very useful to extend the domain of this metafunction to include class types with a result_type member type. The rationale of this is that in many ways bft::result_type is a simplified version of boost::result_of -- simplified so that the types of the invokation arguments need not be known. In other words, if both of these compile result_of< Fn( T1, T2, ... ) >::type result_type< Fn >::type compile, they will refer to the same type. (This is also true of the current implementation without my suggested extention.) 10. Syntactic sugar around parameter_types Whilst being able to leverage the full power of the MPL with parameter_types is definitely desireable, it can also faze those less familiar with metaprogramming. I would like to suggest a helper metafunction that extracts a single parameter type: template < typename F, std::size_t N, class ClassTransform = add_reference<_> > struct function_parameter { typedef typedef mpl::at< function_parameters<F, ClassTransform>, N >::type type; }; (I'd suggest base-zero numbering as given here, though this might cause confusion in conjunction with the first_argument_type, second_argument_type typedefs in std::binary_function.) Oh, and I'd also like to suggest a quick comment in the documentation saying what the '_' is that is given as a template argument to add_reference -- a quick using mpl::placeholders::_; in the synopsis would probably be sufficient. 11. Member function arities The documentation to function_arity states that the 'this' pointer is included -- which is what most people would expect. It's also what the implementation does. However in the 'Use Cases' page of documentation, a R (C::*)() function is listed in the first code fragment under the comment '0 parameters'. Although not explicitly contradictory (parameters and arity don't *necessarily* mean the same thing), I think this is potentially confusing. 12. Use cases documentation To be honest, I find this page of the documentation dreadful, which is shame as the rest is quite reasonable. It discusses various scenarios that could benefit from the application of this library, but utterly fails to suggest *how* they would benefit from the library. On the whole page, only one of the library's components is actually mentioned -- the function_pointer metafunction for synthesising function types. But the code fragment is far too incomplete to be of any real use. It's also one of the more complicated examples as it requires using the MPL. By all means include such a example, but not as the only one! 13. Why is bft::components useful? For that matter, what *exactly* does it do? First the documentation says | components<T,ClassTransform> | MPL - Front / Back Extensible Random Access Sequence | of all component types and property tag then it says | Extracts all properties of a callable builtin type, that | is the result type, followed by the parameter types | (including the type of this for member function | pointers). The former is ambiguous -- it doesn't say what it means by 'component types'; and the latter contradicts it by not mentioning the property tag. It also seems not to mention what it actually means by *the* property tag. A function can be variadic or non_variadic; it be default_cc; it may have cv-qualifiers, which in the case of a const volatile function needs to tags to express it. Are these concatenated using bft::tag or appended one-by-one to the end of the MPL sequence? But more importantly, why do we need this metafunction? It does nothing that separate invokations of result_type, parameter_types and the various is_* metafunctions can't achieve. And I would *rather* see separate invokations of the these -- it would make for much more readble code. Oh, and the name isn't very descriptive. 14. Type sythesis ... And now I see what bft::components is supposed to achieve. But I still don't find the idea of merging the result type, parameter types and arbitrary other information together into a single type list at all intuitive. What's wrong with: template < typename Result, class ParameterSeq, class PropertiesTag = null_tag > struct function_type; Much more readable, in my opinion. Having said that, I think these metafunctions are an important piece of functionality. It's merely their interface I'm concerned about. I hope these points have been useful -- and sorry for such a long post if they haven't! Cheers Richard Smith

Hi Richard, Richard Smith wrote:
Throughout these comments, I am assuming the namespace alias
namespace bft = boost::function_types;
1. Namespace
The public interface to this library is in the boost::function_types namespace. As a propsective user of the library, it feels very much like an extension to the type_traits library, and that leaves me wondering why the library isn't in the main boost namespace with the other type_traits functionality.
Well, we can probably pull some of the templates down to boost (see below) in case the library gets accepted into Boost.
2. Use of Tags
After a second glance, it's clear that one reason for having separate namespaces is to avoid name collisions -- we already have a boost::is_function, for example. And this leaves me wondering how boost::is_function differs from bft::is_function as the names fail to convey the distinction. So far as I can see, the additional Tag template parameter is the only difference, and only three of the possible property tags are meaningful: variadic, non_variadic and default_cc.
No. In fact is_function is a candidate to be put in namespace boost. The tag parameter has a default, so boost::is_function and bft::is_function are compatible.
The majority of the time I can't imagine myself making much use of any of these tags. Are they really worth while? The 'Rationale' section of the documentation addresses this and considers some alternatives:
<snip quote>
What about the third possibility: leave it up to the client to sythesise these more complicated examples. It will involve adding a few more templates: notably is_variadic and is_default_cc. Then, instead of writing
bft::is_function< T, bft::variadic >::value
you would write
boost:is_function<T>::value && boost::is_variadic<T>::value
... which is not significantly more verbose. I think this would be my prefered interface as it would avoid the duplication of functionality between the type_traits library (and the potential for confusion that this would cause).
I think, I don't like it. It's too irregular for my taste.
3. Extensibility
The internal bitmask implementation underlying the property tags does not appear to allow extension by a user.
Hell - don't mess with the bitmask - it's a library internal ;-) !
For example, there is a default_cc tag; suppose I want to add support for querying the some other calling convention.
You can.
Can I write a fastcall_cc tag?
Even better: It's written for you.
Scanning through the implementation it would appear not -- certainly there's no documentation on how to do so.
All you have to do is set the macros BOOST_FT_CC_NAMES and BOOST_FT_CC_<name> appropriately (see Reference->Macros).
If a tag-like syntax is considered desireable, wouldn't something like
template < typename T, template <typename> class UnaryTypeTrait > struct is_function : integral_constant< bool, is_function<T>::value && UnaryTypeTrait<T>::value > {};
be more extensible? Or does this have to work with compilers that can't handle template template parameters?
No. But it's supposed to work with MPL-Lambda Expression, which do not allow template template parameters.
4. Naming
It seems unlikely that the default_cc tag will be particularly heavily used. Given this, why not give it a more meaningful name: default_calling_convention perhaps?
For the default configuration all calling convention tags currently have a _cc suffix. But we might as well s/_cc/_calling_convention/g.
5. Extern "C" linkage
<snip>
(mostly because you can't put extern "C" within a template or atemplate within an extern "C" block).
Exactly.
6. What is a 'callable builtin'?
So far as I can see, the C++ Standard does not define 'callable', so I asume that the pertinent definition is the one in TR1, 3.1/6:
| A /callable type/ is a pointer to function, a pointer to | member function, a pointer to member data, or a class | type whose objects can appear immediately to the left of | a function call operator.
By this definition, function types are not callable, nor are references to functions, bizarre as this may seem.
<snip>
Though I'm not wholly convinced with TR1's definition of 'callable', this is as close as it gets to a standard definition, and it would seem wise to make pointers to member data return true.
I also think 'builtin' needs documenting even if only superficially; to me 'builtin' is a synonym to 'fundamental', though there are no callable fundamental types.
Obviously these terms do not work well... We need a definition or we have to find a better way of naming the beast.
7. What is a 'callable scalar'?
The term 'scalar' is defined in 3.9/10:
| Arithmentic types, enumeration types, pointer types, and | pointer to member types, and cv-qualified versions of | these types are collectively called scalar types.
Note that references, whether to functions or otherwise, are *not* scalars. The is_callable_scalar metafunction returns true for references to functions. This is wrong.
Doh!
Also, why is is_callable_scalar useful? I'm not sure I can think of a use case; and if I could, I imagine it would be rare enough that it wouldn't be much of an inconvenience to sythesise it from is_function and is_callable_builtin.
Good point. Probably we can just throw it out.
8. 'Tag Types' documentation
In several places, the 'Tag Types' documentation incorrectly gives types two leading underscores.
Where?!
9. Extending result_type
Perhaps this is beyond the intended scope of the library,
Yes.
but I think it would be very useful to extend the domain of this metafunction to include class types with a result_type member type.
No, that's what boost::result_of is for. FunctionTypes is only about the type system. One of its examples is a reimplementation of boost::result_of, in fact. <snip>
10. Syntactic sugar around parameter_types
Whilst being able to leverage the full power of the MPL with parameter_types is definitely desireable, it can also faze those less familiar with metaprogramming.
I would like to suggest a helper metafunction that extracts a single parameter type:
template < typename F, std::size_t N, class ClassTransform = add_reference<_> > struct function_parameter { typedef typedef mpl::at< function_parameters<F, ClassTransform>, N >::type type; };
(I'd suggest base-zero numbering as given here, though this might cause confusion in conjunction with the first_argument_type, second_argument_type typedefs in std::binary_function.)
Good practice is to typedef the sequence and use mpl::at_c on the new name. It also leads to more readable code, IMO. Further, I think it's a good idea to encourage people to use the MPL.
Oh, and I'd also like to suggest a quick comment in the documentation saying what the '_' is that is given as a template argument to add_reference -- a quick
using mpl::placeholders::_;
in the synopsis would probably be sufficient.
I'll add that.
11. Member function arities
The documentation to function_arity states that the 'this' pointer is included -- which is what most people would expect. It's also what the implementation does. However in the 'Use Cases' page of documentation, a R (C::*)() function is listed in the first code fragment under the comment '0 parameters'. Although not explicitly contradictory (parameters and arity don't *necessarily* mean the same thing), I think this is potentially confusing.
I'm afraid that making the same point while addressing this issue could be more confusing. Any suggestions?
12. Use cases documentation
To be honest, I find this page of the documentation dreadful, which is shame as the rest is quite reasonable. It discusses various scenarios that could benefit from the application of this library, but utterly fails to suggest *how* they would benefit from the library.
On the whole page, only one of the library's components is actually mentioned -- the function_pointer metafunction for synthesising function types. But the code fragment is far too incomplete to be of any real use. It's also one of the more complicated examples as it requires using the MPL. By all means include such a example, but not as the only one!
Did you follow the links? There's a lot of inline documentation in the files. But maybe I don't get your point. Further, as mentioned above, I'm all against MPL-fear-mongering.
13. Why is bft::components useful?
For that matter, what *exactly* does it do?
It gives a one-type respresentation of all properties. And IIRC there is at least one example that shows it in action.
First the documentation says
| components<T,ClassTransform> | MPL - Front / Back Extensible Random Access Sequence | of all component types and property tag
then it says
| Extracts all properties of a callable builtin type, that | is the result type, followed by the parameter types | (including the type of this for member function | pointers).
The former is ambiguous -- it doesn't say what it means by 'component types'; > and the latter contradicts it by not mentioning the property tag.
It also seems not to mention what it actually means by *the* property tag. A function can be variadic or non_variadic; it be default_cc; it may have cv-qualifiers, which in the case of a const volatile function needs to tags to express it. Are these concatenated using bft::tag or appended one-by-one to the end of the MPL sequence?
The expression models two concepts.
But more importantly, why do we need this metafunction? It does nothing that separate invokations of result_type, parameter_types and the various is_* metafunctions can't achieve. And I would *rather* see separate invokations of the these -- it would make for much more readble code.
Oh, and the name isn't very descriptive.
Well, read it like function_type's::components . I've seen names worse than that...
14. Type sythesis
... And now I see what bft::components is supposed to achieve.
But I still don't find the idea of merging the result type, parameter types and arbitrary other information together into a single type list at all intuitive.
What's wrong with:
template < typename Result, class ParameterSeq, class PropertiesTag = null_tag > struct function_type;
Much more readable, in my opinion.
Maybe. But I'm not sure.
Having said that, I think these metafunctions are an important piece of functionality. It's merely their interface I'm concerned about.
I hope these points have been useful -- and sorry for such a long post if they haven't!
Nothing to be sorry about. Thank you for your review! Regards, Tobias

"Tobias Schwinger" <tschwinger@neoscientists.org> wrote in message news:eivt2r$isl$1@sea.gmane.org...
Further, I think it's a good idea to encourage people to use the MPL.
Actually it seems a bit pointless to use mpl sequences for this library. Why not use tuple or Fusion sequences? There isnt much you can do with functions at compile time and Fusion has much better runtime functionality. regards Andy Little

Andy Little wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote in message news:eivt2r$isl$1@sea.gmane.org...
Further, I think it's a good idea to encourage people to use the MPL.
Actually it seems a bit pointless to use mpl sequences for this library. Why not use tuple or Fusion sequences?
Because there are no runtime values!?

Hi Tobias, Thanks for your response. There are a few additional comments below. Tobias Schwinger wrote:
Richard Smith wrote:
2. Use of Tags
After a second glance, it's clear that one reason for having separate namespaces is to avoid name collisions -- we already have a boost::is_function, for example. And this leaves me wondering how boost::is_function differs from bft::is_function as the names fail to convey the distinction. So far as I can see, the additional Tag template parameter is the only difference, and only three of the possible property tags are meaningful: variadic, non_variadic and default_cc.
No. In fact is_function is a candidate to be put in namespace boost. The tag parameter has a default, so boost::is_function and bft::is_function are compatible.
Won't this cause problems with Boost.TR1 which simply pulls in boost::is_function? namespace std { namespace tr1 { using ::boost::is_function; } } I can't see anything in TR1 that specifically allows implentations to add additional template parameters to the <type_traits> metafunctions. (TR1:4.1/1 says it is still a UnaryTypeTrait, but that's a different issue.) Nothing in section 17.4.4 of the C++ Standard (which I assume applies to TR1) allows implementations to add template parameters and it isn't allowed under the 'as if' rule either (see DR94). Plus, it'll break my code ;-( I've got at least one piece of code that takes a type trait as a template template parameter.
[...] instead of writing
bft::is_function< T, bft::variadic >::value
you would write
boost:is_function<T>::value && boost::is_variadic<T>::value
I think, I don't like it. It's too irregular for my taste.
I'm not sure what exactly you mean by 'irregular', but I take it that boost::mpl::and_< boost::is_function<T>, boost::is_variadic<T> >::value is no better? To me, it's a question of diminishing returns -- where the metafunctions are likely to commonly required it makes sense for a library to provide convenience interfaces that bundle everything together; but when they're less common, they can be combined manually by the user. The question is where that distinction occurs.
3. Extensibility
All you have to do is set the macros BOOST_FT_CC_NAMES and BOOST_FT_CC_<name> appropriately (see Reference->Macros).
OK. I hadn't noticed that. I like that. Incidentally, are there any compilers (I'm not aware of any) that specify a calling convention other than with the syntax void (calling_convention *)(); ... for example, does anything use void (*)() calling_convention; or calling_convention void (*)(); And if so, can the library handle it?
If a tag-like syntax is considered desireable, wouldn't something like
template < typename T, template <typename> class UnaryTypeTrait > struct is_function
be more extensible?
[...] it's supposed to work with MPL-Lambda Expression, which do not allow template template parameters.
OK, that's a serious problem. But MPL lambda expressions can provide an answer too -- make the second, tag parameter a lambda expression: is_function< T, is_scalar<_> >
4. Naming
For the default configuration all calling convention tags currently have a _cc suffix. But we might as well s/_cc/_calling_convention/g.
That would have my vote, but it's a minor point.
5. Extern "C" linkage
<snip>
(mostly because you can't put extern "C" within a template or atemplate within an extern "C" block).
Exactly.
The is_union type trait doesn't really work, but it still exists. I think it would be good if the documentation said that extern "C" functions (at least in those compilers that correctly fold language linkage into the type) *shouldn't* be matched by default_cc, but that without some as yet unspecified compiler support, they will incorrectly match. Likewise I think an extern_c_cc that (currently) never matches would be good.
6. What is a 'callable builtin'?
So far as I can see, the C++ Standard does not define 'callable', so I asume that the pertinent definition is the one in TR1, 3.1/6:
| A /callable type/ is a pointer to function, a pointer to | member function, a pointer to member data, or a class | type whose objects can appear immediately to the left of | a function call operator.
By this definition, function types are not callable, nor are references to functions, bizarre as this may seem.
<snip>
Though I'm not wholly convinced with TR1's definition of 'callable', this is as close as it gets to a standard definition, and it would seem wise to make pointers to member data return true.
What are your thoughts on adding support for pointers to member data to the library? I guess it depends to what extra you see this as an extension to the Boost.TypeTraits library for manipulating function types, and to what extent it is viewed as a utility component for use in implementing function wrappers and so on.
8. 'Tag Types' documentation
In several places, the 'Tag Types' documentation incorrectly gives types two leading underscores.
Where?!
In the non_cv reference: | Equivalent to __tag<__non_const,__non_volatile>, but | involves fewer template instantiations when evaluated. Also in const_non_volatile, volatile_non_const and cv_qualfied. Actually, is the documentation in the zip file up to date? It has [last-revision $Date: 2005/05/21 13:27:00 $].
10. Syntactic sugar around parameter_types
Whilst being able to leverage the full power of the MPL with parameter_types is definitely desireable, it can also faze those less familiar with metaprogramming.
I would like to suggest a helper metafunction that extracts a single parameter type: [...]
Good practice is to typedef the sequence and use mpl::at_c on the new name. It also leads to more readable code, IMO.
If you only need to access a single parameter type (for example because you know the function is unary) foo< parmeter_type< F, 0 >::type >(); is much more readable than typedef parameter_types< F > params; foo< at_c< params, 0 >::type >(); at least in my opinion.
Further, I think it's a good idea to encourage people to use the MPL.
Agreed. But I also have to work in the real world, and unfortunately there are a lot of people who, rightly or wrongly, are intimidated by the MPL. By all means encourage people to use it, but it shouldn't be at the cost of making the simplest of operations more complicated.
11. Member function arities
The documentation to function_arity states that the 'this' pointer is included -- which is what most people would expect. It's also what the implementation does. However in the 'Use Cases' page of documentation, a R (C::*)() function is listed in the first code fragment under the comment '0 parameters'. Although not explicitly contradictory (parameters and arity don't *necessarily* mean the same thing), I think this is potentially confusing.
I'm afraid that making the same point while addressing this issue could be more confusing. Any suggestions?
Remove both the '// 0 parameters' and '// 1 parameters' comments, leaving the '// ...' and subsequent comment at the end?
12. Use cases documentation
To be honest, I find this page of the documentation dreadful, which is shame as the rest is quite reasonable. It discusses various scenarios that could benefit from the application of this library, but utterly fails to suggest *how* they would benefit from the library.
On the whole page, only one of the library's components is actually mentioned -- the function_pointer metafunction for synthesising function types. But the code fragment is far too incomplete to be of any real use. It's also one of the more complicated examples as it requires using the MPL. By all means include such a example, but not as the only one!
Did you follow the links? There's a lot of inline documentation in the files. But maybe I don't get your point.
Yeah, I followed the links, and the examples are very good. But what I think what's missing are any short code fragments using the Boost.FunctionTypes library that illustrate the basic point. In your 'Introduction', you've got a few good, brief code fragments; they provide a flavour of how the library is used, are aimed at about the right level. The 'Use cases' page starts well -- the accept_function example illustrates the basic point of the library. But the next sentence is where, IMO, the problem starts: | The combination with a tuples library that provides an | invoker component, such as Boost.Fusion, allows to build | callback facilities that are entirely free of repetitive | code as shown by the interpreter example ... and indeed it does. It's a good example. But as the first example, as a reader of the documentation, I'm hoping to see something a little more skeletal, first, to illustrate the use case.
13. Why is bft::components useful?
For that matter, what *exactly* does it do?
It gives a one-type respresentation of all properties.
How does it distinguish between member functions and non-member functions? Or doesn't it? Given that this affects the invokation syntax, it seems an important property.
And IIRC there is at least one example that shows it in action.
I can't see any uses of it in the example/ directory.
First the documentation says
| components<T,ClassTransform> | MPL - Front / Back Extensible Random Access Sequence | of all component types and property tag
then it says
| Extracts all properties of a callable builtin type, that | is the result type, followed by the parameter types | (including the type of this for member function | pointers).
The former is ambiguous -- it doesn't say what it means by 'component types'; and the latter contradicts it by not mentioning the property tag.
At the very least, this contradiction should be fixed -- either the MPL sequence does or it doesn't contain the tag.
It also seems not to mention what it actually means by *the* property tag. A function can be variadic or non_variadic; it be default_cc; it may have cv-qualifiers, which in the case of a const volatile function needs to tags to express it. Are these concatenated using bft::tag or appended one-by-one to the end of the MPL sequence?
The expression models two concepts.
Sorry, which expression models which two concepts? Or more concretely, what is the MPL sequence for components< double __cdecl (C::*)(float, int, ...) const volatile > is it double, float, int, tag< cdecl_cc, variadic, const_qualified, volatile_qualified > If so, is the order of the parameters to the tag<> template specified? And is there a mechansim for querying the parts of it? Cheers Richard Smith

Richard Smith wrote:
<snip>
No. In fact is_function is a candidate to be put in namespace boost. The tag parameter has a default, so boost::is_function and bft::is_function are compatible.
Won't this cause problems with Boost.TR1 which simply pulls in boost::is_function?
namespace std { namespace tr1 { using ::boost::is_function; } }
<snip> I don't see a big of a problem to say namespace std { namespace tr1 { template<typename T> struct is_function : boost::is_function<T> { }; } } (or alike) instead.
[...] instead of writing
bft::is_function< T, bft::variadic >::value
you would write
boost:is_function<T>::value && boost::is_variadic<T>::value
I think, I don't like it. It's too irregular for my taste.
I'm not sure what exactly you mean by 'irregular', but I take it that
boost::mpl::and_< boost::is_function<T>, boost::is_variadic<T> >::value
is no better?
No. It's the parts of the library that become asymmetric between decomposition and synthesis.
3. Extensibility
All you have to do is set the macros BOOST_FT_CC_NAMES and BOOST_FT_CC_<name> appropriately (see Reference->Macros).
OK. I hadn't noticed that. I like that.
Incidentally, are there any compilers (I'm not aware of any) that specify a calling convention other than with the syntax
void (calling_convention *)();
... for example, does anything use
void (*)() calling_convention;
Don't know about this one.
or
calling_convention void (*)();
This one exists (although I'm not sure whether it's still widely used). Borland uses void calling_convention (*)();
And if so, can the library handle it?
Yes. There is another configuration macro called BOOST_FT_SYNTAX.
If a tag-like syntax is considered desireable, wouldn't something like
template < typename T, template <typename> class UnaryTypeTrait > struct is_function
be more extensible?
Do we need extensibility here? The type system is finite, after all.
[...] it's supposed to work with MPL-Lambda Expression, which do not allow template template parameters.
OK, that's a serious problem. But MPL lambda expressions can provide an answer too -- make the second, tag parameter a lambda expression:
is_function< T, is_scalar<_> >
Well, yes and no. How would you express 'is_member_function_pointer<T, const_qualified>'? It would require an own lambda evaluator...
5. Extern "C" linkage
<snip>
(mostly because you can't put extern "C" within a template or atemplate within an extern "C" block).
Exactly.
The is_union type trait doesn't really work, but it still exists.
Oh, boost::is_union only works with compilers that provide extensions for type introspection (and, AFAIK, there are compilers that do so).
I think it would be good if the documentation said that extern "C" functions (at least in those compilers that correctly fold language linkage into the type) *shouldn't* be matched by default_cc, but that without some as yet unspecified compiler support, they will incorrectly match.
is_function_pointer< ext_c_func_ptr, default_cc >::value works correctly. It tells me whether ext_c_func_ptr has the C++ default calling convention. Adding a note to the docs won't hurt, though.
Likewise I think an extern_c_cc that (currently) never matches would be good.
For what? <snip>
What are your thoughts on adding support for pointers to member data to the library? I guess it depends to what extra you see this as an extension to the Boost.TypeTraits library for manipulating function types, and to what extent it is viewed as a utility component for use in implementing function wrappers and so on.
Supporting data members is trivial. So of what help could the library be?
8. 'Tag Types' documentation
In several places, the 'Tag Types' documentation incorrectly gives types two leading underscores.
Where?!
In the non_cv reference:
| Equivalent to __tag<__non_const,__non_volatile>, but | involves fewer template instantiations when evaluated.
Also in const_non_volatile, volatile_non_const and cv_qualfied.
Actually, is the documentation in the zip file up to date? It has [last-revision $Date: 2005/05/21 13:27:00 $].
I see. Thanks for spotting. It's a documentation problem. The names with the underscores should be identifier names for QuickBook macros that expand to hyperlinks -- obviously the definitions are missing...
10. Syntactic sugar around parameter_types
Whilst being able to leverage the full power of the MPL with parameter_types is definitely desireable, it can also faze those less familiar with metaprogramming.
I would like to suggest a helper metafunction that extracts a single parameter type: [...]
Good practice is to typedef the sequence and use mpl::at_c on the new name. It also leads to more readable code, IMO.
If you only need to access a single parameter type (for example because you know the function is unary)
foo< parmeter_type< F, 0 >::type >();
In that special case mpl::at_c<parameter_types<F>,0>::type isn't inconvenient enough to justify "convenience clutter" in the interface, IMO.
is much more readable than
typedef parameter_types< F > params; foo< at_c< params, 0 >::type >();
at least in my opinion.
Further, I think it's a good idea to encourage people to use the MPL.
Agreed. But I also have to work in the real world, and unfortunately there are a lot of people who, rightly or wrongly, are intimidated by the MPL.
I can understand the objective of keeping application code free of metaprogramming magic. In this case you better stay away from all metaprogramming libraries (including this one and TypeTraits) and building template-based interfaces altogether.
By all means encourage people to use it, but it shouldn't be at the cost of making the simplest of operations more complicated.
I really don't think it's the case, here.
11. Member function arities
The documentation to function_arity states that the 'this' pointer is included -- which is what most people would expect. It's also what the implementation does. However in the 'Use Cases' page of documentation, a R (C::*)() function is listed in the first code fragment under the comment '0 parameters'. Although not explicitly contradictory (parameters and arity don't *necessarily* mean the same thing), I think this is potentially confusing.
I'm afraid that making the same point while addressing this issue could be more confusing. Any suggestions?
Remove both the '// 0 parameters' and '// 1 parameters' comments, leaving the '// ...' and subsequent comment at the end?
OK. Will do.
12. Use cases documentation
To be honest, I find this page of the documentation dreadful, which is shame as the rest is quite reasonable. It discusses various scenarios that could benefit from the application of this library, but utterly fails to suggest *how* they would benefit from the library.
On the whole page, only one of the library's components is actually mentioned -- the function_pointer metafunction for synthesising function types. But the code fragment is far too incomplete to be of any real use. It's also one of the more complicated examples as it requires using the MPL. By all means include such a example, but not as the only one!
Did you follow the links? There's a lot of inline documentation in the files. But maybe I don't get your point.
Yeah, I followed the links, and the examples are very good.
Thanks.
But what I think what's missing are any short code fragments using the Boost.FunctionTypes library that illustrate the basic point.
Isn't this done in the introduction?
In your 'Introduction', you've got a few good, brief code fragments; they provide a flavour of how the library is used, are aimed at about the right level.
The 'Use cases' page starts well -- the accept_function example illustrates the basic point of the library. But the next sentence is where, IMO, the problem starts:
| The combination with a tuples library that provides an | invoker component, such as Boost.Fusion, allows to build | callback facilities that are entirely free of repetitive | code as shown by the interpreter example
... and indeed it does. It's a good example. But as the first example, as a reader of the documentation, I'm hoping to see something a little more skeletal, first, to illustrate the use case.
I see. Some "glue text" might allow me to swap the first two examples. The second example is a lot simpler (and I'd use forward declarations so the code becomes more obvious)...
13. Why is bft::components useful?
For that matter, what *exactly* does it do?
It gives a one-type respresentation of all properties.
How does it distinguish between member functions and non-member functions? Or doesn't it?
It doesn't.
Given that this affects the invokation syntax, it seems an important property.
It is, but there are other components that deal with type categorization.
And IIRC there is at least one example that shows it in action.
I can't see any uses of it in the example/ directory.
You're right. Obviously I did not remember correctly.
First the documentation says
| components<T,ClassTransform> | MPL - Front / Back Extensible Random Access Sequence | of all component types and property tag
then it says
| Extracts all properties of a callable builtin type, that | is the result type, followed by the parameter types | (including the type of this for member function | pointers).
The former is ambiguous -- it doesn't say what it means by 'component types'; and the latter contradicts it by not mentioning the property tag.
At the very least, this contradiction should be fixed -- either the MPL sequence does or it doesn't contain the tag.
I agree.
It also seems not to mention what it actually means by *the* property tag. A function can be variadic or non_variadic; it be default_cc; it may have cv-qualifiers, which in the case of a const volatile function needs to tags to express it. Are these concatenated using bft::tag or appended one-by-one to the end of the MPL sequence?
The expression models two concepts.
Sorry, which expression models which two concepts?
components<T,ClassTransform>
Or more concretely, what is the MPL sequence for
components< double __cdecl (C::*)(float, int, ...) const volatile >
is it
A sequence of:
double, float, int,
and a property tag with the meaning of:
tag< cdecl_cc, variadic, const_qualified, volatile_qualified >
If so, is the order of the parameters to the tag<> template specified?
The properties in it are disjoint, so the meaning stays the same regardless of the ordering.
And is there a mechansim for querying the parts of it?
There is an implementation in the library internals but I didn't expose it, because I couldn't find a single use case. Thanks again for your comments. Regards, Tobias

Tobias, Sorry for not replying to your comments sooner. On Fri, 10 Nov 2006, Tobias Schwinger wrote:
Richard Smith wrote:
[...] instead of writing
bft::is_function< T, bft::variadic >::value
you would write
boost:is_function<T>::value && boost::is_variadic<T>::value
I think, I don't like it. It's too irregular for my taste.
I'm not sure what exactly you mean by 'irregular'
[...] It's the parts of the library that become asymmetric between decomposition and synthesis.
I'm still not entirely sure I'm following you. Do you mean you want two metafunctions such that synthesise< decompose<_> > is the identity? If so, you've already lost that because components doesn't store whether you have a function, function reference, function pointer or member function pointer.
5. Extern "C" linkage
The is_union type trait doesn't really work, but it still exists.
Oh, boost::is_union only works with compilers that provide extensions for type introspection (and, AFAIK, there are compilers that do so).
That's exactly my point. A good quality compiler that supports type introspection and that properly implements language linkage in the type system would presumably allow for querying language linkage.
I think it would be good if the documentation said that extern "C" functions (at least in those compilers that correctly fold language linkage into the type) *shouldn't* be matched by default_cc, but that without some as yet unspecified compiler support, they will incorrectly match.
is_function_pointer< ext_c_func_ptr, default_cc >::value
works correctly. It tells me whether ext_c_func_ptr has the C++ default calling convention.
Even on a compiler (e.g. Comeau) that folds language linkage into the type system? On such a system, surely extern "C" typedef void (*ext_c_func_ptr)(); is_function_pointer< ext_c_func_ptr, default_cc >::value *should* return false? (I appreciate it may not, but this is an problem with the implementation, albeit a problem that can't necessarily be solved at the moment.)
Adding a note to the docs won't hurt, though.
Likewise I think an extern_c_cc that (currently) never matches would be good.
For what?
So that a compiler supporting type introspection and language linkage in the type system can implement it properly. For example, in Digital Mars __cdecl and extern "C" are synonyms, so you already have support for it on that platform.
<snip>
What are your thoughts on adding support for pointers to member data to the library? I guess it depends to what extra you see this as an extension to the Boost.TypeTraits library for manipulating function types, and to what extent it is viewed as a utility component for use in implementing function wrappers and so on.
Supporting data members is trivial. So of what help could the library be?
Consistency. TR1 defines 'callable' types to include data members; Boost.Function, Boost.Bind and Boost.Lambda all support data mebers as unary functions. The is_callable_builtin<> metafunctions are just for convenience -- they can be implemented by mpl::or_'ing together is_function, is_function_reference, is_function_pointer, and is_member_function_pointer. I'm suggesting that you should include is_member_object_pointer too.
10. Syntactic sugar around parameter_types
parmeter_type< F, 0 >::type
In that special case
mpl::at_c<parameter_types<F>,0>::type
isn't inconvenient enough to justify "convenience clutter" in the interface, IMO.
Well, I disagree, and I think implementing this level of convenience function will serve to encourage people to use the library.
I can understand the objective of keeping application code free of metaprogramming magic. In this case you better stay away from all metaprogramming libraries (including this one and TypeTraits) and building template-based interfaces altogether.
Perhaps it's not intended to, but, frankly, that sounds incredibly patronising. I find it absolutely extraordinary that someone on this list would advise people who find the MPL intimidating to "stay away from ... building template-based interfaces altogether". There's a whole world of difference between the two; and like it or not, in quite a lot of circles, the MPL *does* have a (perhaps largely undeserved) aura of impenetrability. I'm all for trying to rectify this and encourage its use, but advising people to avoid all template code isn't the way to achieve this.
13. Why is bft::components useful?
I can't see any uses of it in the example/ directory.
You're right. Obviously I did not remember correctly.
Would it be possible to see a use case?
Sorry, which expression models which two concepts?
components<T,ClassTransform>
OK. And which two concepts does it model? I can see that it's an MPL sequence, but what else is it? -- Richard Smith

Richard Smith wrote:
Tobias,
Sorry for not replying to your comments sooner.
Never mind - I'm happy about any movement after several days of silence :-).
On Fri, 10 Nov 2006, Tobias Schwinger wrote:
Richard Smith wrote:
[...] instead of writing
bft::is_function< T, bft::variadic >::value
you would write
boost:is_function<T>::value && boost::is_variadic<T>::value
I think, I don't like it. It's too irregular for my taste.
I'm not sure what exactly you mean by 'irregular'
[...] It's the parts of the library that become asymmetric between decomposition and synthesis.
I'm still not entirely sure I'm following you. Do you mean you want two metafunctions such that
synthesise< decompose<_> >
is the identity?
In a way, yes.
If so, you've already lost that because components doesn't store whether you have a function, function reference, function pointer or member function pointer.
Well, it does store this information, but there is no interface exposing it to the user ;-), but that's not my point. My point is simply that you can create all the types that you can take apart.
5. Extern "C" linkage
<snip>
is_function_pointer< ext_c_func_ptr, default_cc >::value
works correctly. It tells me whether ext_c_func_ptr has the C++ default calling convention.
Even on a compiler (e.g. Comeau) that folds language linkage into the type system?
No. Thanks for making me aware of that problem! OK, now I get your point.
On such a system, surely
extern "C" typedef void (*ext_c_func_ptr)(); is_function_pointer< ext_c_func_ptr, default_cc >::value
*should* return false? (I appreciate it may not, but this is an problem with the implementation, albeit a problem that can't necessarily be solved at the moment.)
extern "C" { void __stdcall ext_c_func() { /* ... */ } } :-P Actually (although the standard says something different) language linkage should tell the linker how to do symbol lookup. The only type system issue is the calling convention part and the mere existence of calling convention specifiers (which are not part of the standard, which probably explains its weirdness) actually /should/ suffice as support for type introspection.
For example, in Digital Mars __cdecl and extern "C" are synonyms, so you already have support for it on that platform.
I'd call this ^^^ the proper way to implement things. This problem has to be addressed, one way or the other. It is possible to check for T being a function by checking whether T* converts to void const volatile*, but that won't get us very far, but detecting is only half the rent. There is no way to take it apart, AFAICS. I'd prefer documenting that types with external language linkage are not supported, for now.
What are your thoughts on adding support for pointers to member data to the library? I guess it depends to what extra you see this as an extension to the Boost.TypeTraits library for manipulating function types, and to what extent it is viewed as a utility component for use in implementing function wrappers and so on.
Supporting data members is trivial. So of what help could the library be?
Consistency. TR1 defines 'callable' types to include data members; Boost.Function, Boost.Bind and Boost.Lambda all support data mebers as unary functions. The is_callable_builtin<> metafunctions are just for convenience -- they can be implemented by mpl::or_'ing together is_function, is_function_reference, is_function_pointer, and is_member_function_pointer. I'm suggesting that you should include is_member_object_pointer too.
I'm not fully convinced since that "callable builtin" term doesn't work without a definition, anyway. From my feeling data members should be handled at a higher level of abstraction (at the same place where we normalize between function objects and functions).
10. Syntactic sugar around parameter_types
parmeter_type< F, 0 >::type
In that special case
mpl::at_c<parameter_types<F>,0>::type
isn't inconvenient enough to justify "convenience clutter" in the interface, IMO.
Well, I disagree, and I think implementing this level of convenience function will serve to encourage people to use the library.
I can understand the objective of keeping application code free of metaprogramming magic. In this case you better stay away from all metaprogramming libraries (including this one and TypeTraits) and building template-based interfaces altogether.
Perhaps it's not intended to, but, frankly, that sounds incredibly patronising.
Certainly not intended! Did you perhaps misread me?
I find it absolutely extraordinary that someone on this list would advise people who find the MPL intimidating to "stay away from ... building template-based interfaces altogether".
I'm really just citing my own style guide. I try to separate between library and application code, keeping the latter free of templates; the application code may heavily use the library code in its implementation (.cpp) files and some library components (such as e.g. Boost.Function) may even make it to the headers. There may be exceptions to this rule, however, the more minimalist the headers look like, the better (avoid dependencies, prefer loose coupling and encapsulate by coherence - design your headers to "keep the client't compiler cool"...).
There's a whole world of difference between the two;
Writing portable template code with the MPL vs. writing hopefully (but probably non-) portable template code without? Just kidding (sorry, it was just too tempting). Portability of templates is getting better, after all...
and like it or not, in quite a lot of circles, the MPL *does* have a (perhaps largely undeserved) aura of impenetrability. I'm all for trying to rectify this and encourage its use, but advising people to avoid all template code isn't the way to achieve this.
Your argumentation reads like I'm forcing people to read the source of that library...
13. Why is bft::components useful?
I can't see any uses of it in the example/ directory.
You're right. Obviously I did not remember correctly.
Would it be possible to see a use case?
E.g. boost::function< typename function_type< components<F, shared_ptr<_> > >::type > There are some more in this post: http://tinyurl.com/whkmd
Sorry, which expression models which two concepts?
components<T,ClassTransform>
OK. And which two concepts does it model? I can see that it's an MPL sequence, but what else is it?
It's both a tag and an MPL sequence. Thanks, Tobias

Is this correct in the docs? If so it seems weird: result_type< bool(&)(int) >::type // is int regards Andy Little
participants (5)
-
Andy Little
-
Hartmut Kaiser
-
Richard Smith
-
Tobias Schwinger
-
Tom Brinkman