[mpl] has_template_xxx patch

Hello, I would like a Metafunction similar to the one created by BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF but that would detect nested template members rather than nested typedefs and classes. It would allow you to do something like the following: #include <utility> #include <boost/mpl/assert.hpp> #include <boost/mpl/has_template_xxx.hpp> #include <boost/utility/result_of.hpp> // Create has_template_result to detect nested members like // template<class T> struct result {}. // The first macro argument is the member name and the second argument // is the number of template parameters. BOOST_MPL_HAS_TEMPLATE_XXX_TRAIT_DEF(result, 1) struct pair_maker { template<typename F> struct result; template<typename F, typename Arg0, typename Arg1> struct result<F(Arg0, Arg1)> { typedef std::pair<Arg0, Arg1> type; }; template<typename Arg0, typename Arg1> typename result<pair_maker(Arg0, Arg1)>::type operator()(Arg0 a0, Arg1 a1) const { return std::make_pair(a0, a1); } }; int main() { using namespace boost; typedef char value_type; BOOST_MPL_ASSERT(( has_template_result< pair_maker, pair_maker(value_type, value_type) > )); typedef result_of< pair_maker(value_type, value_type) >::type result_type; value_type x, y; pair_maker f; result_type result = f(x, y); } The attached patch implements this. Apply with 'patch -p0 < djw_has_template.patch' from the boost root directory. It's based on the implementation of BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF and works basically the same way. The patch creates two files boost/mpl/has_template_xxx.hpp and boost/mpl/aux_/config/has_template_xxx.hpp. Similarly to has_xxx, when the maco BOOST_MPL_CFG_NO_HAS_TEMPLATE_XXX is defined the has_template_xxx::value is always false or a user supplied default. At this time, I'm unable to write all the various compiler workarounds that boost/mpl/has_xxx.hpp includes. BOOST_MPL_CFG_NO_HAS_TEMPLATE_XXX is defined for every workaround mentioned in boost/mpl/has_xxx.hpp. I've tested it with gcc 3.3, 3.4, 4.0, and 4.1 and it seems to work fine. If there's any interest, let me know and I'll supply documentation and tests. Thanks! Daniel Walker

On 3/20/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
Hello,
I would like a Metafunction similar to the one created by BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF but that would detect nested template members rather than nested typedefs and classes. It would allow you to do something like the following:
#include <utility> #include <boost/mpl/assert.hpp> #include <boost/mpl/has_template_xxx.hpp> #include <boost/utility/result_of.hpp>
// Create has_template_result to detect nested members like // template<class T> struct result {}. // The first macro argument is the member name and the second argument // is the number of template parameters. BOOST_MPL_HAS_TEMPLATE_XXX_TRAIT_DEF(result, 1)
struct pair_maker { template<typename F> struct result; template<typename F, typename Arg0, typename Arg1> struct result<F(Arg0, Arg1)> { typedef std::pair<Arg0, Arg1> type; };
template<typename Arg0, typename Arg1> typename result<pair_maker(Arg0, Arg1)>::type operator()(Arg0 a0, Arg1 a1) const { return std::make_pair(a0, a1); } };
int main() { using namespace boost;
typedef char value_type; BOOST_MPL_ASSERT(( has_template_result< pair_maker, pair_maker(value_type, value_type) > ));
typedef result_of< pair_maker(value_type, value_type) >::type result_type;
value_type x, y; pair_maker f; result_type result = f(x, y); }
The attached patch implements this. Apply with 'patch -p0 < djw_has_template.patch' from the boost root directory. It's based on the implementation of BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF and works basically the same way. The patch creates two files boost/mpl/has_template_xxx.hpp and boost/mpl/aux_/config/has_template_xxx.hpp. Similarly to has_xxx, when the maco BOOST_MPL_CFG_NO_HAS_TEMPLATE_XXX is defined the has_template_xxx::value is always false or a user supplied default. At this time, I'm unable to write all the various compiler workarounds that boost/mpl/has_xxx.hpp includes. BOOST_MPL_CFG_NO_HAS_TEMPLATE_XXX is defined for every workaround mentioned in boost/mpl/has_xxx.hpp. I've tested it with gcc 3.3, 3.4, 4.0, and 4.1 and it seems to work fine. If there's any interest, let me know and I'll supply documentation and tests.
One up for this. I've needed it to detect the 'sig<...>' metafunctions to distinguish Boost.Lambda function objects from other polymorphic function objects. gpd

On 3/20/07, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
One up for this. I've needed it to detect the 'sig<...>' metafunctions to distinguish Boost.Lambda function objects from other polymorphic function objects.
That's similar to what I am using it for. I'm about to post a patch for result_of so that it can work with Boost.Lambda function objects. Daniel

Hello, I've been looking into getting member template detection to work on various compilers, and I have a question regarding SFINAE. I hope someone can help. All the compilers I've tried reject the following. template<class T> struct foo {}; template<class T, class U> void f(T,U) {} template<class T, class U> void f(foo<T,U>) {} // error: wrong number of template // arguments (2, should be 1) provided for // 'template<class T> struct foo' template<class T, class U> struct bar {}; template<class T, class U> struct bar<foo<T,U>, U> {}; // error: wrong number of template // arguments (2, should be 1) provided for // 'template<class T> struct foo' int main() { f(0,0); typedef bar<int,int> type; } Is this a substitution failure? Should the 2nd overload of f() be removed from the set of candidate functions during overload resolution? Should something similar be true for the partial specialization of bar<>? Or is this standard compliant behavior? I've worked out pretty much every other issue, but I don't think I can get this one to work if this is a compiler bug. Thanks. Daniel

Your foo struct only has one template argument On 3/30/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
Hello,
I've been looking into getting member template detection to work on various compilers, and I have a question regarding SFINAE. I hope someone can help. All the compilers I've tried reject the following.
template<class T> struct foo {};
template<class T, class U> void f(T,U) {}
template<class T, class U> void f(foo<T,U>) {} // error: wrong number of template // arguments (2, should be 1) provided for // 'template<class T> struct foo'
template<class T, class U> struct bar {};
template<class T, class U> struct bar<foo<T,U>, U> {}; // error: wrong number of template // arguments (2, should be 1) provided for // 'template<class T> struct foo'
int main() { f(0,0); typedef bar<int,int> type; }
Is this a substitution failure? Should the 2nd overload of f() be removed from the set of candidate functions during overload resolution? Should something similar be true for the partial specialization of bar<>? Or is this standard compliant behavior?
I've worked out pretty much every other issue, but I don't think I can get this one to work if this is a compiler bug.
Thanks. Daniel
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

It has been my experience that it causes an error as I think (not positive) that some syntax checking is done even if it will not get instantiated. On 3/30/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/30/07, Tom Lahoda <tlahoda@gmail.com> wrote:
Your foo struct only has one template argument
I know. My question is should that cause an error or a substitution failure, which is not an error.
Daniel _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 3/30/07, Tom Lahoda <tlahoda@gmail.com> wrote:
It has been my experience that it causes an error as I think (not positive) that some syntax checking is done even if it will not get instantiated.
That's fine. I'm just thinking about test cases. Is the error standard compliant? Should I write tests for this case and excluded them for current compiler releases anticipating that at some point in the future they will accept this? Or is this mandated by the standard, and I should mention it in the documentation as a caveat?
On 3/30/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/30/07, Tom Lahoda <tlahoda@gmail.com> wrote:
Your foo struct only has one template argument
I know. My question is should that cause an error or a substitution failure, which is not an error.

Unfortunately I don't know if it is standard compliant or not as I'm not a standards expert, just a C++ enthusiast interested in Boost and not a Boost member. Sorry I couldn't be of more help. Hopefully one of the standard experts on the list will weigh in. On 3/30/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
It has been my experience that it causes an error as I think (not
On 3/30/07, Tom Lahoda <tlahoda@gmail.com> wrote: positive)
that some syntax checking is done even if it will not get instantiated.
That's fine. I'm just thinking about test cases. Is the error standard compliant? Should I write tests for this case and excluded them for current compiler releases anticipating that at some point in the future they will accept this? Or is this mandated by the standard, and I should mention it in the documentation as a caveat?
On 3/30/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/30/07, Tom Lahoda <tlahoda@gmail.com> wrote:
Your foo struct only has one template argument
I know. My question is should that cause an error or a substitution failure, which is not an error.
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 Daniel Walker Sent: Friday, March 30, 2007 4:57 PM To: boost@lists.boost.org Subject: Re: [boost] [mpl] has_template_xxx patch
That's fine. I'm just thinking about test cases. Is the error standard compliant? Should I write tests for this case and excluded them for current compiler releases anticipating that at some point in the future they will accept this? Or is this mandated by the standard, and I should mention it in the documentation as a caveat?
According to "C++ Templates" (Vandevoorde/Josuttis) SFINAE is there to make overloading of template functions applicable. IMHO, it means that template argument deduction must be successful and that only failures to create valid types from the deduced arguments (by substituting function call parameters by them) are prevented from erroring out. In your case, the argument deduction already fails, because there is no type foo<T,U>. cheers, aa -- Andreas Ames | Programmer | Comergo GmbH | ames AT avaya DOT com Sitz der Gesellschaft: Stuttgart Registergericht: Amtsgericht Stuttgart - HRB 22107 Geschäftsführer: Andreas von Meyer zu Knonow, Udo Bühler, Thomas Kreikemeier

Daniel Walker wrote:
On 3/30/07, Tom Lahoda <tlahoda@gmail.com> wrote:
Your foo struct only has one template argument
I know. My question is should that cause an error or a substitution failure, which is not an error.
In your example: template<class T> struct foo {}; template<class T, class U> void f( foo<T, U> ) {} there are no substitutions. Your f definition is simply ill-formed.

Quoting Daniel Walker:
Is this a substitution failure?
There is no substitution in your code, so a substitution failure cannot happen. Here is a real substitution, that does fail properly: template<class T> struct foo { template<class U> struct bar; }; template<class T, class U> void f(T,U) {} template<class T, class U> void f(T, typename foo<T>::template bar<T,U>) {} int main() { f(0,0); } I am not sure if it will help you though, as I don't know if you can afford to protect the class you want to test (bar) into a dummy template (foo), so that a substitution happens. No template typedef... Best regards, Guillaume

On 3/30/07, Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> wrote:
Quoting Daniel Walker:
Is this a substitution failure?
There is no substitution in your code, so a substitution failure cannot happen. Here is a real substitution, that does fail properly:
template<class T> struct foo { template<class U> struct bar; };
template<class T, class U> void f(T,U) {}
template<class T, class U> void f(T, typename foo<T>::template bar<T,U>) {}
int main() { f(0,0); }
OK, thanks for the help. I was trying to simplify my code to replicate the error I'm getting, and I may have gone to far. Can you tell me if the following contains a substitution? struct foo { template<class U> struct bar; }; template<class T, class U, class V> struct baz { template<class W> static int f(W*, ...) {} template<class W> static int f(W*, typename W::template bar<U,V>*) {} static const int size = sizeof(f<T>(0, 0)); // error: wrong number of template arguments (2, should be // 1) provided for `template<class U> struct foo::bar' }; int main() { baz<foo, int, int>::size; } This is closer to the has_xxx implementation. Any suggestions would be greatly appreciated!
I am not sure if it will help you though, as I don't know if you can afford to protect the class you want to test (bar) into a dummy template (foo), so that a substitution happens. No template typedef...
Best regards,
Guillaume
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Quoting Daniel Walker:
OK, thanks for the help. I was trying to simplify my code to replicate the error I'm getting, and I may have gone to far. Can you tell me if the following contains a substitution?
static const int size = sizeof(f<T>(0, 0));
At first sight, I would have said that it does. But on further reflexion, it probably does not, as there is no deduction from the argument types. But if you use f((T*)0,0) instead, then it should work. Best regards, Guillaume

On 3/30/07, Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> wrote:
Quoting Daniel Walker:
OK, thanks for the help. I was trying to simplify my code to replicate the error I'm getting, and I may have gone to far. Can you tell me if the following contains a substitution?
static const int size = sizeof(f<T>(0, 0));
At first sight, I would have said that it does. But on further reflexion, it probably does not, as there is no deduction from the argument types. But if you use f((T*)0,0) instead, then it should work.
Your right. Excellent! This doesn't work on MSVC 8.0, however. I believe it doesn't work using template-based SFINAE on MSVC as well. If I can't work around it, would it be ok if I exclude MSVC from tests for has_template_xxx rejecting types containing member templates with the correct name but incorrect arguments? Everything else works on VC 8.0 and VC 7.1. If the bug is fixed in MSVC or if someone else comes up with a work around, we can then include MSVC in these tests. Thanks! Daniel

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Daniel Walker Sent: Friday, March 30, 2007 6:14 PM Subject: Re: [boost] [mpl] has_template_xxx patch
On 3/30/07, Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> wrote:
Quoting Daniel Walker:
static const int size = sizeof(f<T>(0, 0));
At first sight, I would have said that it does. But on further reflexion, it probably does not, as there is no deduction from the argument types. But if you use f((T*)0,0) instead, then it should work.
Your right. Excellent!
This doesn't work on MSVC 8.0, however. I believe it doesn't work using template-based SFINAE on MSVC as well. If I can't work around it, would it be ok if I exclude MSVC from tests for has_template_xxx rejecting types containing member templates with the correct name but incorrect arguments? Everything else works on VC 8.0 and VC 7.1. If the bug is fixed in MSVC or if someone else comes up with a work around, we can then include MSVC in these tests.
After rereading 14.8.2 [temp.deduct] I'd say, both forms are compliant. Rejecting one (with explicit template arguments) and accepting the other should definitely be a bug. At least, I can't see how both forms would differ regarding SFINAE. cheers, aa -- Andreas Ames | Programmer | Comergo GmbH | ames AT avaya DOT com Sitz der Gesellschaft: Stuttgart Registergericht: Amtsgericht Stuttgart - HRB 22107 Geschäftsführer: Andreas von Meyer zu Knonow, Udo Bühler, Thomas Kreikemeier

On 3/30/07, Ames Andreas <Andreas.Ames@comergo.com> wrote:
On 3/30/07, Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> wrote:
Quoting Daniel Walker:
static const int size = sizeof(f<T>(0, 0));
At first sight, I would have said that it does. But on further reflexion, it probably does not, as there is no deduction from the argument types. But if you use f((T*)0,0) instead, then it should work.
Your right. Excellent!
This doesn't work on MSVC 8.0, however. I believe it doesn't work using template-based SFINAE on MSVC as well. If I can't work around it, would it be ok if I exclude MSVC from tests for has_template_xxx rejecting types containing member templates with the correct name but incorrect arguments? Everything else works on VC 8.0 and VC 7.1. If the bug is fixed in MSVC or if someone else comes up with a work around, we can then include MSVC in these tests.
After rereading 14.8.2 [temp.deduct] I'd say, both forms are compliant. Rejecting one (with explicit template arguments) and accepting the other should definitely be a bug. At least, I can't see how both forms would differ regarding SFINAE.
I was testing with gcc 4.1.2. So, you're saying in the above example it should accept both of the following: static const int size = sizeof(f<T>(0, 0)); static const int size = sizeof(f((T*)0,0)); That was my first impression as well, but I wasn't sure if they'd be equivalent or not. I may try to send the gcc folks a bug report and see what they think. At least there's one way to get gcc to accept it. How should SFINAE applied to user-defined class template specializations work? The following is close to the has_xxx implementation for VC8. typedef void sfinae_select_tag; template<class T> struct sfinae_selector { typedef sfinae_select_tag type; }; template<class T, class T0, class T1, class U = sfinae_select_tag> struct has_bar_impl { static const bool value = false; }; template<class T, class T0, class T1> struct has_bar_impl< T, T0, T1 , typename sfinae_selector< typename T::template bar<T0, T1> >::type
{ static const bool value = true; };
template<class T, class T0, class T1> struct has_bar : has_bar_impl<T, T0, T1> {}; //error: wrong number of template arguments (2, should be 1) //provided for `template<class U> struct foo::bar' struct foo { template<class U> struct bar; }; int main() { has_bar<foo, int, int>::value; } Should this work according to the standard? Anyone have ideas for coercing msvc into not issuing a compilation error in this case? Thanks! Daniel

On 3/30/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/30/07, Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> wrote:
Quoting Daniel Walker:
OK, thanks for the help. I was trying to simplify my code to replicate the error I'm getting, and I may have gone to far. Can you tell me if the following contains a substitution?
static const int size = sizeof(f<T>(0, 0));
At first sight, I would have said that it does. But on further reflexion, it probably does not, as there is no deduction from the argument types. But if you use f((T*)0,0) instead, then it should work.
Your right. Excellent!
I spoke too soon. Your suggestion got ride of the compilation error but now the overload resolution always selects f(W*, ...), even when the template does exist with the correct number of args. Here's an example that will accept the member templates correctly and reject member templates that have the wrong name. But if the names match and the parameters don't the compilation error comes back again. struct foo { template<class U, class V> struct xxx; }; struct bar { template<class U, class V> struct yyy; }; struct baz { template<class U> struct xxx; }; typedef char (&yes)[1]; typedef char (&no) [2]; template<class T, class U, class V> struct has_xxx { static no f(...) {} template<class W> static yes f(W*, typename W::template xxx<U,V>* = 0) {} static const bool value = sizeof(f((T*)0)) == sizeof(yes); // error: wrong number of template arguments (2, should be 1) // provided for `template<class U> struct baz::xxx' }; int main() { int assert[has_xxx<foo, int, int>::value]; int assert_not_yyy[!has_xxx<bar, int, int>::value]; int assert_not_biary[!has_xxx<baz, int, int>::value]; // comment out to remove error } gcc and msvc both have problems with this but apparently for different reasons. It seems like there's a consensus that SFINAE should allow this code to compile on a standard compliant compiler. I'm going to contact the gcc folks at least to try to get more info. I'll write test cases for this, but exclude them from the latest gcc and msvc. Let me know if I'm misunderstanding something and please let me know if you find a work around for this problem. Thanks, Daniel

On 3/30/07, Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> wrote:
I am not sure if it will help you though, as I don't know if you can afford to protect the class you want to test (bar) into a dummy template (foo), so that a substitution happens. No template typedef...
OK, I think I got it. The trick was getting the "dummy" template. The following works on gcc 3.4, 4.0, and 4.1 (not 3.3 and older). typedef char (&yes)[1]; typedef char (&no) [2]; template< class T > struct type_substitute {}; template< template < class T, class U > class> struct biary_template_substitute {}; template< class T, class U, class V > struct has_xxx { template< class W > static no f(type_substitute< W >*, ...); template< class W > static yes f(type_substitute< W >* , biary_template_substitute< W::template xxx >*); static const bool value = sizeof(f<T>(0, 0)) == sizeof(yes); }; struct foo { template<class U, class V> struct xxx; }; struct bar { template<class U, class V> struct yyy; }; struct baz { template<class U> struct xxx; }; int main() { int assert_has_xxx[has_xxx<foo, int, int>::value]; int assert_not_xxx[!has_xxx<bar, int, int>::value]; int assert_not_unary[!has_xxx<baz, int, int>::value]; } I'm certain this is standard compliant because I took the idea directly from the 3rd example in section 14.8.2 "Attempting to use a type in a nested-name-specifier of a qualified-id when that type does not contain the specified member ...". This also works on Comeau 4.3.9 Alpha online except for the assert_not_unary case. Apparently this is a common problem among compilers. It doesn't work on msvc 7.1 or 8.0 at all. So, though the other two cases work on msvc (not with the implementation above but there's another on this thread that works), to handle this case in msvc we still need a work around. Thanks for the help! Daniel

On 3/31/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/30/07, Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> wrote:
I am not sure if it will help you though, as I don't know if you can afford to protect the class you want to test (bar) into a dummy template (foo), so that a substitution happens. No template typedef...
OK, I think I got it. The trick was getting the "dummy" template.
I think I just found a workaround for msvc as well. The workaround relies on a bug I noticed while working on this involving member templates with no required parameters (all the parameters have defaults). I worked around this problem, and I'll have a comment in my final patch describing it. Anyway, I think this bug can be used to work around the issue of rejecting types with member templates that have the correct name but incorrect number of arguments. The following code works on msvc 8.0 and 7.1. typedef char (&yes)[1]; typedef char (&no) [2]; typedef void substitute_tag; template< template< class U, class V > class T > struct binary_template_substitute { typedef substitute_tag type; }; template<class T, class T0, class T1, class U = substitute_tag> struct has_xxx_impl { static const bool value = false; }; template<class T, class T0, class T1> struct has_xxx_impl< T, T0, T1 , typename binary_template_substitute< typename T::template xxx<>
::type { static const bool value = true; };
template<class T, class T0, class T1> struct has_xxx : has_xxx_impl<T, T0, T1> {}; struct foo { template<class U, class V> struct xxx; }; struct bar { template<class U, class V> struct yyy; }; struct baz { template<class U> struct xxx; }; int main() { int assert_has_xxx[has_xxx<foo, int, int>::value]; int assert_not_xxx[!has_xxx<bar, int, int>::value]; int assert_not_unary[!has_xxx<baz, int, int>::value]; } On Monday I'm going to try to incorporate this into my has_xxx for templates implementation, run through all my test cases, and see if I can submit a revised patch. Daniel

Hello, I've attached a rewrite of the patch I previously submitted that includes documentation and new tests in MPL's test suite. Apply with 'patch -p0 < djw_has_xxx_template.patch' from the boost root directory. This implementation is based on comp.lang.c++.moderated USENET postings from Rani Sharoni (2002-03-17, http://tinyurl.com/2u2a9f) and Aleksey Gurtovoy (2002-03-19, http://tinyurl.com/376y7c), the current has_xxx implementation (especially ideas in the msvc 8.0 implementation from Daniel Wallin, I believe), the 3rd code example in section 14.2.8 of the standard, and the discussion on this thread (especially postings from Guillaume Melquiond who pointed out to me the need for a seperate "substitute" template). Also, thanks to Aleksey Gurtovoy and David Abrahams for implementing has_xxx in the first place and especially for including citations of the USENET discussions in has_xxx.hpp. They were invaluable. By testing combinations of different members, member names, member types, and member template arities, I have 142 individual tests (i.e. assertions) for detecting member templates. Here is the pass/fail rate for the compilers I tested. gcc 3.4, 4.0, 4.1 - 142/142 gcc 3.3 - 139/142 msvc 7.1, 8.0: 142/142 comeau 4.3.8 alpha online: 93/142 (I had to run it through the preprocessor and then paste it on the website's form) The tests that fail on gcc 3.3 are for rejecting member templates with the correct name but incorrect number of parameters. Comeau also cannot do this and additionally cannot reject members with the correct name that aren't templates (typedefs and structs) and cannot detect member templates with the correct name but no required parameters (all parameters have defaults). Other changes from my previous patch include: 1) changed the name of BOOST_MPL_HAS_TEMPLATE_XXX_TRAIT_DEF to BOOST_MPL_HAS_XXX_TEMPLATE_DEF, same for NAMED_DEF version. It's more concise. Also, by default the name of the generated metafunction is a concatination of 'has_' and the name of the nested template rather than 'has_template_' and the name of the nested template. This is also done for brievity's sake. 2) included the macro definitions in has_xxx.hpp rather than creating new files. These are closely related, and at some point in the future the implementations for has_xxx for nested types and has_xxx for nested templates could be folded together to improve code reuse. 3) created the following new documentation files - libs/mpl/doc/src/refmanual/CFG_NO_HAS_TEMPLATE_XXX.rst - libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_DEF.rst - libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_NAMED_DEF.rst I wasn't sure how to generate the HTML and pdf manuals. 4) added the tests to has_xxx.cpp and no_has_xxx.cpp I'm assuming this is too late to be considered for 1.34, so I built the patch off the cvs trunk rather than RC_1_34_0. I replaced my previous patch on SF patch tracker with the current one. As for future work: 1) Though the two most common compilers, gcc 4 and msvc 7.1/8.0, pass all the tests, it would be nice to have work arounds so that all compilers pass all the tests. 2) I believe this can be extended along the lines of John Madsen's comp.lang.c++.moderated posting (1999-11-12, http://tinyurl.com/2wqorl) to test for other sorts of members by creating new substitute templates for SFINAE. I made an initial try at detecting member data and had some success. If there's interest I could look into extending has_xxx for member templates into a more complete set of compile time type introspection metafunctions... something like has_member_data, has_member_function, has_member_type, has_member_template. The last two metafunction would supersede the currect has_xxx and my has_xxx for templates. Let me know if you have trouble applying the patch or if you have suggests to improve this. Thanks! Daniel P.S. The example of using BOOST_MPL_HAS_XXX_TEMPLATE_DEF that I posted with my original patch should now look like the following (if you want to copy and past it for a quick test). #include <utility> #include <boost/mpl/assert.hpp> #include <boost/mpl/has_xxx.hpp> #include <boost/utility/result_of.hpp> // Create has_result to detect nested members like // template<class T> struct result {}. // The first macro argument is the member name and the second argument // is the number of template parameters. BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result, 1) struct pair_maker { template<typename F> struct result; template<typename F, typename Arg0, typename Arg1> struct result<F(Arg0, Arg1)> { typedef std::pair<Arg0, Arg1> type; }; template<typename Arg0, typename Arg1> typename result<pair_maker(Arg0, Arg1)>::type operator()(Arg0 a0, Arg1 a1) const { return std::make_pair(a0, a1); } }; int main() { using namespace boost; typedef char value_type; BOOST_MPL_ASSERT(( has_result< pair_maker, pair_maker(value_type, value_type) > )); typedef result_of< pair_maker(value_type, value_type)
::type result_type;
value_type x, y; pair_maker f; result_type result = f(x, y); }

on Mon Apr 02 2007, "Daniel Walker" <daniel.j.walker-AT-gmail.com> wrote:
I've attached a rewrite of the patch I previously submitted that includes documentation and new tests in MPL's test suite. Apply with 'patch -p0 < djw_has_xxx_template.patch' from the boost root directory.
Fantastic, Daniel! Could you please submit this to the SF patch tracker and assign it to Aleksey? Thanks -- Dave Abrahams Boost Consulting www.boost-consulting.com Don't Miss BoostCon 2007! ==> http://www.boostcon.com

On 4/4/07, David Abrahams <dave@boost-consulting.com> wrote:
on Mon Apr 02 2007, "Daniel Walker" <daniel.j.walker-AT-gmail.com> wrote:
I've attached a rewrite of the patch I previously submitted that includes documentation and new tests in MPL's test suite. Apply with 'patch -p0 < djw_has_xxx_template.patch' from the boost root directory.
Fantastic, Daniel! Could you please submit this to the SF patch tracker and assign it to Aleksey?
Thanks! The patch is on SF patch tracker and assigned to Aleksey. Daniel
participants (7)
-
Ames Andreas
-
Daniel Walker
-
David Abrahams
-
Giovanni Piero Deretta
-
Guillaume Melquiond
-
Peter Dimov
-
Tom Lahoda