 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Howard Gardner Guest
|
Posted: Tue Jul 11, 2006 2:37 am Post subject: supports_syntax facility, does this code really work? |
|
|
/*
This program exercises the facility supports_syntax, which
would be handy to use in conjuntion with boost::enable_if.
supports_syntax< SUBJECT, SYNTAX >::value is true if and
only if SUBJECT supports the syntax that SYNTAX checks for.
There are no requirements on SUBJECT. SYNTAX must be
written carefully. This program demonstrates checking
for a member type, a member variable, a member function,
and a nonmember function. The example syntax here is
deliberately minimal. I've tried some more complex
syntax: sometimes I've gotten it to work, and sometimes
I haven't.
I arrived at this implementation through a little research
(sizeof trick, SFINAE) and heroic quantities of experiment.
This code would be very useful(!) in template metaprogramming,
but I'm afraid of it. Since I arrived at it through experiment,
it's quite possible that it just exploits bugs in the compiler
that I'm using. I keep trying to make simplifications that
break it, so there are certainly things about it that I don't
understand.
I'll give the two big mysteries names:
1) syntax dummy parameter
All of the syntax checks are template classes taking one
template parameter, which is a dummy. If I take this dummy
parameter away from syntax_member_type, the code still works.
If I take it away from syntax_member_variable,
syntax_member_function, or syntax_nonmember_function, though,
the code breaks.
2) nonmember_function double overload
Why do I have to supply TWO overloads of nonmember function?
If I supply only one, the code breaks.
*/
#include <fstream>
using std::cout;
using std::endl;
// An empty class to be used as a dummy type
struct
dummy
{
};
// Another empty class to be used as a dummy type
struct
another_dummy
{
};
// An empty class that has none of the syntax I'm checking for
struct
has_nothing
{
};
// A class that defines a type
struct
has_member_type
{
typedef
int
member_type;
};
// Checks that a type is defined
template< typename xDummy = dummy >
// syntax dummy parameter - take this away, still works
struct
syntax_member_type
{
template
<
typename xSubject,
typename = typename xSubject::member_type
};
// A class that has a member variable
struct
has_member_variable
{
int
member_variable;
};
// Checks for a member variable
template< typename xDummy = dummy >
// syntax dummy parameter - take this away, breaks code
struct
syntax_member_variable
{
template
<
typename xSubject,
int (xSubject::*) = &xSubject::member_variable
};
// A class that has a member function
struct
has_member_function
{
void
member_function();
};
// Checks for a member function
template< typename xDummy = dummy >
// syntax dummy parameter - take this away, breaks code
struct
syntax_member_function
{
template
<
typename xSubject,
void (xSubject::*)() = &xSubject::member_function
};
// A class that is used as a parameter for
// a nonmember function
struct
has_nonmember_function
{
};
void
nonmember_function(has_nonmember_function);
// Checks for a nonmember function
void
nonmember_function(dummy);
void
nonmember_function(another_dummy);
/*
nonmember_function overload - there have to be at least two
overloads of nonmember function or the code breaks. As it
sits, there are three. I can take one of them away and all
is well. If I take two of them away, the code breaks.
*/
template< typename xDummy = dummy >
// syntax dummy parameter - take this away, breaks code
struct
syntax_nonmember_function
{
template
<
typename xSubject,
void (*)( xSubject ) = nonmember_function
};
// The engine
template< typename xSubject, typename xSyntax >
struct supports_syntax
{
private:
// yes and no are guaranteed to have different sizes
typedef
char
yes;
class
no
{
yes c[2];
};
// Return a yes if there is a match
template< typename uxSubject >
static
yes
func
(
typename xSyntax::template match< uxSubject > *
);
// Return a no if there is no match
template< typename uxSubject >
static
no
func
(
...
);
public:
static
const bool
value
= ( sizeof( func< xSubject >( 0 ) ) == sizeof( yes ) );
};
int
main()
{
// Member type
cout
<< supports_syntax
<
has_member_type, syntax_member_type< >
<< endl;
cout
<< supports_syntax
<
has_nothing,
syntax_member_type< >
<< endl;
// Member variable
cout
<< supports_syntax
<
has_member_variable,
syntax_member_variable< >
<< endl;
cout
<< supports_syntax
<
has_nothing,
syntax_member_variable< >
<< endl;
// Member function
cout
<< supports_syntax
<
has_member_function,
syntax_member_function< >
<< endl;
cout
<< supports_syntax
<
has_nothing,
syntax_member_function< >
<< endl;
// Non member function
cout
<< supports_syntax
<
has_nonmember_function,
syntax_nonmember_function< >
<< endl;
cout
<< supports_syntax
<
has_nothing,
syntax_nonmember_function< >
<< endl;
}
[ 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
|
|