 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Slawomir Lisznianski Guest
|
Posted: Sun Oct 16, 2005 9:53 am Post subject: MPL: detecting if T provides nested type member? |
|
|
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
|
Posted: Sun Oct 16, 2005 11:18 pm Post subject: Re: MPL: detecting if T provides nested type member? |
|
|
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
|
Posted: Mon Oct 17, 2005 11:52 am Post subject: Re: MPL: detecting if T provides nested type member? |
|
|
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
|
Posted: Wed Oct 19, 2005 8:35 am Post subject: Re: MPL: detecting if T provides nested type member? |
|
|
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
|
Posted: Fri Oct 21, 2005 9:13 am Post subject: Re: MPL: detecting if T provides nested type member? |
|
|
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 |
|
 |
|
|
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
|
|