C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

MPL: detecting if T provides nested type member?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Slawomir Lisznianski
Guest





PostPosted: Sun Oct 16, 2005 9:53 am    Post subject: MPL: detecting if T provides nested type member? Reply with quote



Hello,

Given these two types:

struct has_return_type { typedef int return_type; };
struct lacks_return_type { };

Is there a way to distinguish between has_return_type and
lacks_return_type?

I'd like to assume some default type in case user doesn't provide the
nested type explicitly.

Cheers,

--
Slawomir Lisznianski
Programs for Research Machinery, LLC.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David Abrahams
Guest





PostPosted: Sun Oct 16, 2005 11:18 pm    Post subject: Re: MPL: detecting if T provides nested type member? Reply with quote



Slawomir Lisznianski <newsgroup (AT) paramay (DOT) com> writes:

Quote:
Hello,

Given these two types:

struct has_return_type { typedef int return_type; };
struct lacks_return_type { };

Is there a way to distinguish between has_return_type and
lacks_return_type?

#include <boost/mpl/has_xxx.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(return_type)

will define a unary has_return_type metafunction.

Quote:
I'd like to assume some default type in case user doesn't provide the
nested type explicitly.

I think you should look at the result_of<> metafunction; it may be
relevant to what you're doing. Going with an existing protocol will
make your code more interoperable.
http://www.boost.org/libs/utility/utility.htm#result_of

HTH,
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Greg Herlihy
Guest





PostPosted: Mon Oct 17, 2005 11:52 am    Post subject: Re: MPL: detecting if T provides nested type member? Reply with quote



Slawomir Lisznianski wrote:
Quote:
Hello,

Given these two types:

struct has_return_type { typedef int return_type; };
struct lacks_return_type { };

Is there a way to distinguish between has_return_type and
lacks_return_type?

I'd like to assume some default type in case user doesn't provide the
nested type explicitly.

Using an existing template library such as Boost's mpl would probably
be the most portable and hassle-free solution. But just in case you
find it more fun to write your own template metaprograms, here's a
program to get you going:

#include <iostream>

struct has_return_type { typedef int return_type; };
struct lacks_return_type { };

enum ResultValue { no = sizeof(long), Yes = sizeof(char) };

struct TTest
{
template <class U>
static char check( typename U::return_type );

template <class U>
static long check( ... );
};

int main()
{
std::cout << "has_return_type typedefs "return_type": ";

if (sizeof(TTest::check std::cout << "yes" << std::endl;
else
std::cout << "no" << std::endl;

std::cout << "lacks_return_type typedefs "return_type": ";

if (sizeof(TTest::check std::cout << "yes" << std::endl;
else
std::cout << "no" << std::endl;
}

Output:
has_return_type typedefs "return_type": yes
lacks_return_type typedefs "return_type": no

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Slawomir Lisznianski
Guest





PostPosted: Wed Oct 19, 2005 8:35 am    Post subject: Re: MPL: detecting if T provides nested type member? Reply with quote

Greg Herlihy wrote:
Quote:
Using an existing template library such as Boost's mpl would probably
be the most portable and hassle-free solution.

Yup, BOOST_MPL_HAS_XXX_TRAIT_DEF(return_type) works fine.

Quote:
find it more fun to write your own template metaprograms, here's a
program to get you going:

This solution won't work in all cases though. Consider this:

struct user_type { };

struct has_return_type { typedef user_type return_type; };
struct lacks_return_type { };

Since `user_type' doesn't provide a constructor which takes an integral
type, the compiler overload resolution always picks "..." and prints:

has_return_type typedefs "return_type": no
lacks_return_type typedefs "return_type": no

which is not what we want. I was able to fix your solution by modifying
the signature of your first `check' to:

template <class T>
static char check(void(*)(typename T::return_type));

The above implementation relies on properly working SFINAE (too much to
ask?)

Also, you assumed that long and char types were of different sizes,
which the standard doesn't guarantee.

Cheers,

--
Slawomir Lisznianski
Paramay Group, LLC
"Programs for Research Machinery"

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Greg Herlihy
Guest





PostPosted: Fri Oct 21, 2005 9:13 am    Post subject: Re: MPL: detecting if T provides nested type member? Reply with quote

Slawomir Lisznianski wrote:
Quote:
Greg Herlihy wrote:
Using an existing template library such as Boost's mpl would probably
be the most portable and hassle-free solution.

Yup, BOOST_MPL_HAS_XXX_TRAIT_DEF(return_type) works fine.

find it more fun to write your own template metaprograms, here's a
program to get you going:

This solution won't work in all cases though. Consider this:

struct user_type { };

struct has_return_type { typedef user_type return_type; };
struct lacks_return_type { };

Since `user_type' doesn't provide a constructor which takes an integral
type, the compiler overload resolution always picks "..." and prints:

has_return_type typedefs "return_type": no
lacks_return_type typedefs "return_type": no

which is not what we want. I was able to fix your solution by modifying
the signature of your first `check' to:

template <class T
static char check(void(*)(typename T::return_type));

The above implementation relies on properly working SFINAE (too much to
ask?)

I think that a function pointer is too elaborate. A plain pointer seems
safer:

template static char check( typename T::return_type *);

in which case, the 0 parameter passed to check() is not an integral
constant but the null pointer constant.

Quote:
Also, you assumed that long and char types were of different sizes,
which the standard doesn't guarantee.

I gambled that a char and a long would have different sizes on your
compiler - simply because the odds were tremendously in my favor. While
I could have declared a return type class, the more elaborate my
example becomes the more it resembles Boost, and the harder it is to
see what is going on.

As I noted originally, Boost contains the portable version of this
SFINAE technique, my example (over?)simplified the implementation - and
at the cost of portabillity - to illustrate more clearly the essential
technique being applied.

It would be great if C++ offered more overt support for introspection.
But until then, this SPINAE ("substition failure is not an error", in
case anyone is wondering) seems like a reasonably safe technque to me.

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.