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 

Reusable test for presence of a nested typedef?

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





PostPosted: Mon Oct 18, 2004 4:56 pm    Post subject: Reusable test for presence of a nested typedef? Reply with quote



Warning, SFINAE territory ahead...

One typical formulation of a test for a nested typedef result_type
would be, based on Dewhurstian mechanics:

enum yes_no { yes = 1, no = 2 };

template <typename T> char (*may_have_result_type (typename
T::result_type*)) [yes];
template <typename T> char (*may_have_result_type (...)) [no];

template <typename T> stuct has_result_type
{
enum { value = sizeof (*may_have_result_type <T> (NULL)) = yes };
};

So to test if a type U has a result_type, we simply do has_result_type
<U>::value.

But being a guy who loves reuse, especially when he sees his own code
littered with almost similar instances of the above, I wonder whether
there's a general way of doing this (without bashing clients with a
macro) i.e.

has_typedef <U, result_type>::value OR has_typedef <typename
U::result_type>::value ?

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Terje Slettebų
Guest





PostPosted: Mon Oct 18, 2004 8:31 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote



"Glen Low" <glenlow (AT) pixelglow (DOT) com> wrote

Quote:
Warning, SFINAE territory ahead...

And if you fail to understand it, don't treat it as an error. ;)

Quote:
One typical formulation of a test for a nested typedef result_type
would be, based on Dewhurstian mechanics:

enum yes_no { yes = 1, no = 2 };

template <typename T> char (*may_have_result_type (typename
T::result_type*)) [yes];
template <typename T> char (*may_have_result_type (...)) [no];

template <typename T> stuct has_result_type
{
enum { value = sizeof (*may_have_result_type <T> (NULL)) = yes };
};

So to test if a type U has a result_type, we simply do has_result_type
U>::value.

But being a guy who loves reuse, especially when he sees his own code
littered with almost similar instances of the above, I wonder whether
there's a general way of doing this (without bashing clients with a
macro) i.e.

has_typedef <U, result_type>::value OR has_typedef <typename
U::result_type>::value ?

I don't think it can be done without a macro. Many good people have tried.
Smile In the Concept Traits library
([url]http://www.neoscientists.org/boost_library_proposals.html)[/url], where Tobias
Schwinger now is co-author, I used macros for detection where you need a
name, as there are headers (in the type_traits_ext directory of the zip-file
there. Sorry, the docs are only in the archive at the moment) for detection
of:

- Non-static members (variables and functions)
- Static members (variables and functions)
- Nested classes or typedefs
- Nested class templates

Regards,

Terje



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

Back to top
John M. Dlugosz
Guest





PostPosted: Tue Oct 19, 2004 4:22 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote



[email]glenlow (AT) pixelglow (DOT) com[/email] (Glen Low) wrote in message news:<9215d7ac.0410171513.42ac2620 (AT) posting (DOT) google.com>...

Quote:
But being a guy who loves reuse, especially when he sees his own code
littered with almost similar instances of the above, I wonder whether
there's a general way of doing this (without bashing clients with a
macro) i.e.

What happens when you put those templates as template members of a
class which it itself a template on the type name in question? You
imply that it didn't work?

--John

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


Back to top
Glen Low
Guest





PostPosted: Tue Oct 19, 2004 5:59 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote

Quote:
But being a guy who loves reuse, especially when he sees his own code
littered with almost similar instances of the above, I wonder whether
there's a general way of doing this (without bashing clients with a
macro) i.e.

has_typedef <U, result_type>::value OR has_typedef <typename
U::result_type>::value ?

I don't think it can be done without a macro. Many good people have tried.
Smile In the Concept Traits library
([url]http://www.neoscientists.org/boost_library_proposals.html)[/url], where Tobias
Schwinger now is co-author, I used macros for detection where you need a
name, as there are headers (in the type_traits_ext directory of the zip-file
there.

I thought so.

In the end it wasn't too bad. I was using the presence or absence of a
typedef within an enable_if on an partial specialization, it turns out
all I needed was:

template <typename T> struct exists { enum { value = true }; };

Simple, no? Why does it work... well in the partial specialization I
do:

template <typename T, typename Enable = void> class thing;

template <typename T> class thing <T,
typename enable_if ::type>
{
...
};

So in classic SFINAE style, this will be silently dropped from the
overload set when typename T::result_type doesn't exist. The exists +
enable_if combination only serves to form the type "void" when
result_type does exist.

Of course the exists template is of no use in a non-substitutionary
context, and it might yet blow up in my face on a non-gcc compiler,
but I'm fairly sure it will work on a Standard compliant one.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com

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


Back to top
Larry Evans
Guest





PostPosted: Wed Oct 20, 2004 4:26 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote

On 10/18/2004 03:31 PM, Terje Slettebų wrote:
[snip]
Quote:
I don't think it can be done without a macro. Many good people have tried.
Smile In the Concept Traits library
([url]http://www.neoscientists.org/boost_library_proposals.html)[/url], where Tobias
Schwinger now is co-author, I used macros for detection where you need a
name, as there are headers (in the type_traits_ext directory of the zip-file
there. Sorry, the docs are only in the archive at the moment) for detection
of:

- Non-static members (variables and functions)
- Static members (variables and functions)
- Nested classes or typedefs
- Nested class templates

One example of using boost/mpl/aux_/has_xxx.hpp is:

<------------------
//Purpose:
// Test use of SFINAE to detect T::nesting_type for any type, T.
#include namespace boosts
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(nesting_type)
}
struct bool_false{ char c[1];};
struct bool_true { char c[2];};

template<typename T>
struct has_nesting_type
{
template<class C> static bool_true has_nest_type(C::nesting_type*);
template<typename C> static bool_false has_nest_type(...);
enum{ result = sizeof(has_nest_type<T>(0)) == sizeof(bool_true)};
};

struct not_nester{};
struct yes_nester
{
typedef not_nester nesting_type;
};

#include <iostream>
using namespace boost::mpl::aux;
int main(void)
{
std::cout<<"yes_nester="< std::cout<<"not_nester="< std::cout<<"===>boostn";

std::cout<<"yes_nester="<
std::cout<<"not_nester="< return 0;
}
Quote:
------------------
The output of this was:

<------------------
/opt/intel_cc_80/bin/icc -c -MMD -g
-I/home/evansl/prog_dev/boost-root.ln/boost_dev
-I/home/evansl/prog_dev/boost-root.ln -o has_nesting_type.o
has_nesting_type.cpp
/opt/intel_cc_80/bin/icc -g -o has_nesting_type.exe has_nesting_type.o
running has_nesting_type
../has_nesting_type.exe
yes_nester=1
not_nester=0
===>boost
yes_nester=1
not_nester=0

Compilation finished at Sat Mar 6 16:45:52
Quote:
------------------

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

Back to top
Terje Slettebų
Guest





PostPosted: Wed Oct 20, 2004 6:34 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote

"Glen Low" <glenlow (AT) pixelglow (DOT) com> wrote

Quote:
But being a guy who loves reuse, especially when he sees his own code
littered with almost similar instances of the above, I wonder whether
there's a general way of doing this (without bashing clients with a
macro) i.e.

has_typedef <U, result_type>::value OR has_typedef <typename
U::result_type>::value ?

I don't think it can be done without a macro. Many good people have
tried.
Smile In the Concept Traits library
([url]http://www.neoscientists.org/boost_library_proposals.html)[/url], where
Tobias
Schwinger now is co-author, I used macros for detection where you need a
name, as there are headers (in the type_traits_ext directory of the
zip-file
there.

I thought so.

In the end it wasn't too bad. I was using the presence or absence of a
typedef within an enable_if on an partial specialization, it turns out
all I needed was:

template <typename T> struct exists { enum { value = true }; };

Simple, no? Why does it work... well in the partial specialization I
do:

template <typename T, typename Enable = void> class thing;

template <typename T> class thing <T,
typename enable_if ::type
{
...
};

So in classic SFINAE style, this will be silently dropped from the
overload set when typename T::result_type doesn't exist. The exists +
enable_if combination only serves to form the type "void" when
result_type does exist.

Clever...

This does actually work. Come to think of it, I've played with this
technique, as well - I even used the same name: "exists" (!) and found it
marvellous simple. As you say, it doesn't work as a general trait (outside
templates) - which was the original request - but it does work in this
context, of eliminating overloads/specialisations during overload
resolution/specialisation selection.

It does actually generalise to detection of member class template, too:

template <typename T, typename Enable = void>
class thing;

template <typename T>
class thing<
T,
typename boost::enable_if<
exists
Quote:
::type
{

};

class A
{
public:
template<class T>
struct nested {};
};

class B {};

int main()
{
thing<A> a; // Ok
thing<B> b; // Error
}

Moreover, unlike the pointer-to-member type technique, this one actually
works for reference type members, too (you can't form a pointer to a
reference).

And - I just realised - it also works for private members (!), as the type
or class template is never actually used (and hence checked for access),
only checked for existence.

Thanks for reminding me of this technique. :)

Quote:
Of course the exists template is of no use in a non-substitutionary
context, and it might yet blow up in my face on a non-gcc compiler,
but I'm fairly sure it will work on a Standard compliant one.

It works on Intel C++ 7.1, too (EDG).

Regards,

Terje



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

Back to top
Glen Low
Guest





PostPosted: Wed Oct 20, 2004 9:42 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote

Quote:
What happens when you put those templates as template members of a
class which it itself a template on the type name in question? You
imply that it didn't work?

Don't understand, please elaborate with an example.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com

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

Back to top
Glen Low
Guest





PostPosted: Thu Oct 21, 2004 7:40 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote

Quote:
One example of using boost/mpl/aux_/has_xxx.hpp is:
------------------
//Purpose:
// Test use of SFINAE to detect T::nesting_type for any type, T.

I wanted the converse, i.e. to detect T:Mad for any nested type x.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com

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

Back to top
Glen Low
Guest





PostPosted: Thu Oct 21, 2004 7:41 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote

Quote:
This does actually work. Come to think of it, I've played with this
technique, as well - I even used the same name: "exists" (!) and found it
marvellous simple. As you say, it doesn't work as a general trait (outside
templates) - which was the original request - but it does work in this
context, of eliminating overloads/specialisations during overload
resolution/specialisation selection.

Thanks for reminding me of this technique. Smile

No worries.

Unfortunately it can be somewhat deceptive e.g.

template <typename T> struct X <T,
enable_if <T>::value>::type>
{
}

never actually works for an integral type, since the exists
<T::inner>::value causes the substitution failure anyway. Although for
the case of &&, it does work correctly and as you'd expect.

I find it a little more straightforward and reusable than SFINAE on
overload functions; I've changed my macstl code to use it.

Quote:
It works on Intel C++ 7.1, too (EDG).

Works on MS Visual C++ .NET 2003 too.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com

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

Back to top
Terje Slettebų
Guest





PostPosted: Fri Oct 22, 2004 5:16 pm    Post subject: Re: Reusable test for presence of a nested typedef? Reply with quote

"Larry Evans" <cppljevans (AT) cox-internet (DOT) com> wrote

Quote:
On 10/18/2004 03:31 PM, Terje Slettebų wrote:
[snip]
I don't think it can be done without a macro. Many good people have
tried.
Smile In the Concept Traits library
([url]http://www.neoscientists.org/boost_library_proposals.html)[/url], where
Tobias
Schwinger now is co-author, I used macros for detection where you need
a
name, as there are headers (in the type_traits_ext directory of the
zip-file
there. Sorry, the docs are only in the archive at the moment) for
detection
of:

- Non-static members (variables and functions)
- Static members (variables and functions)
- Nested classes or typedefs
- Nested class templates

One example of using boost/mpl/aux_/has_xxx.hpp is:

<snip>

Yeah, but, uhm, here you're showing one version using an MPL macro to do it
(BOOST_MPL_HAS_XXX_TRAIT_DEF(nesting_type)), and then one way to do it by
making the trait class "manually":

Quote:
template<typename T
struct has_nesting_type
{
template has_nest_type(C::nesting_type*);
template<typename C> static bool_false has_nest_type(...);
enum{ result = sizeof(has_nest_type<T>(0)) == sizeof(bool_true)};
};

So... what was the point? OP mentioned both ways, but inquired about the
possibility of doing it without macros, and without having to define a
template like the above.

Regards,

Terje



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