is this code valid ?

G

Gianni Mariani

The 3 compilers I tried all did different things.

gcc 3.4.0 ICE's (Bug 15480)
MS C++ 7.1 has meaningless diags
Comeau accepts the code

Obviously this is not somthing I'll be using until we get the compilers
doing the right thing, but I do want to report the appropriate errors.

BTW, I think the code is valid. It does the thing I was trying to do
before (template has_member) that I got zero response on (...checks
armpits for odor... :) ).



============================================================================

typedef char MPT_False;

struct MPT_True { int m[2]; };


template <unsigned int w_siz>
struct MPT_IntToType
{
typedef char type[ 1 ];
};

template <typename w_D>
struct MPT_Finder_Member
{
template <typename w_T>
static MPT_True finder(
const w_T *,
typename MPT_IntToType<
sizeof(static_cast said:
::type * = 0
);

static MPT_False finder( const w_D * );

};

template <typename w_D >
struct MPT_ContainsFuncMember
{
struct DerivedClass : w_D
{
};

typedef DerivedClass * DerivedClassp;

enum {
value = (
sizeof( MPT_Finder_Member<w_D>::finder( DerivedClassp() ) )
== sizeof( MPT_True )
)
};

};


struct A
{
};

struct B
{
int Function();
};

#include <iostream>

int main()
{
std::cout << MPT_ContainsFuncMember<A>::value << "\n";
std::cout << MPT_ContainsFuncMember<B>::value << "\n";
}

=========================================================================

MSC++ sez

xx5.cpp
xx5.cpp(21) : error C2955: 'MPT_IntToType' : use of class template
requires template argument list
xx5.cpp(11) : see declaration of 'MPT_IntToType'
xx5.cpp(39) : see reference to class template instantiation
'MPT_Finder_Member<w_D>' being compiled
with
[
w_D=A
]
xx5.cpp(60) : see reference to class template instantiation
'MPT_ContainsFuncMember<w_D>' being compiled
with
[
w_D=A
]
xx5.cpp(21) : error C2955: 'MPT_IntToType' : use of class template
requires template argument list
xx5.cpp(11) : see declaration of 'MPT_IntToType'
xx5.cpp(39) : see reference to class template instantiation
'MPT_Finder_Member<w_D>' being compiled
with
[
w_D=B
]
xx5.cpp(61) : see reference to class template instantiation
'MPT_ContainsFuncMember<w_D>' being compiled
with
[
w_D=B
]
 
R

Rob Williscroft

Gianni Mariani wrote in in
comp.lang.c++:
The 3 compilers I tried all did different things.

gcc 3.4.0 ICE's (Bug 15480)
MS C++ 7.1 has meaningless diags
Comeau accepts the code

Obviously this is not somthing I'll be using until we get the compilers
doing the right thing, but I do want to report the appropriate errors.

BTW, I think the code is valid. It does the thing I was trying to do

I think your code [snipped] is legal, but with CBuilderX preview
(EDG frontend) I got output of 0, 0. Did you miss-paste something ?
before (template has_member) that I got zero response on (...checks
armpits for odor... :) ).

Trying to answer your previous post I addapted up this:

#include <iostream>
#include <ostream>

/* addapted from a post by Paul Mensonides in comp.lang.c++.moderated

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=Ox3x8.2363%
24vX.2728%40rwcrnsc53&rnum=5&prev=/groups%3Fq%3Dhas_mem_func%26hl%3Den%
26lr%3D%26ie%3DUTF-8%26domains%3Dwww.victim-prime.dsl.pipex.com%26selm%
3DOx3x8.2363%2524vX.2728%2540rwcrnsc53%26rnum%3D5%26filter%3D0

http://tinyurl.com/2s9z4

The original has an extra level of indirection which I don't see
the need for.

*/

typedef char small_t;
typedef char (& large_t)[256];

template<class T>
struct has_self
{
private:

template< typename U, void (U::*)() > class helper {};

template < typename U >
static small_t check( helper< U, &U::self > * );

template < typename U > static large_t check(...);

public:

enum { value = sizeof(check<T>(0)) == sizeof(small_t) };
};




struct X { };

struct Y
{
void self() {} // Yes
};

struct Z
{
int self; // No - doesn't match member type
};

int main()
{
std::cout
<< "X: " << has_self<X>::value << std::endl
<< "Y: " << has_self<Y>::value << std::endl
<< "Z: " << has_self<Z>::value << std::endl
;
}

I must have missed something because now it would seem this does
what you want, at the time I thought it didn't which is why I
didn't respond, too much googling I guess.

Rob.
 
G

Gianni Mariani

Rob Williscroft wrote:
....
I think your code [snipped] is legal, but with CBuilderX preview
(EDG frontend) I got output of 0, 0. Did you miss-paste something ?

It's not debugged yet ...

The thread below has some nice detail on the topic. Thanks.
Trying to answer your previous post I addapted up this:

#include <iostream>
#include <ostream>

/* addapted from a post by Paul Mensonides in comp.lang.c++.moderated

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=Ox3x8.2363%
24vX.2728%40rwcrnsc53&rnum=5&prev=/groups%3Fq%3Dhas_mem_func%26hl%3Den%
26lr%3D%26ie%3DUTF-8%26domains%3Dwww.victim-prime.dsl.pipex.com%26selm%
3DOx3x8.2363%2524vX.2728%2540rwcrnsc53%26rnum%3D5%26filter%3D0

http://tinyurl.com/2s9z4

The original has an extra level of indirection which I don't see
the need for.

*/

typedef char small_t;
typedef char (& large_t)[256];

template<class T>
struct has_self
{
private:

template< typename U, void (U::*)() > class helper {};

template < typename U >
static small_t check( helper< U, &U::self > * );

template < typename U > static large_t check(...);

public:

enum { value = sizeof(check<T>(0)) == sizeof(small_t) };
};




struct X { };

struct Y
{
void self() {} // Yes
};

struct Z
{
int self; // No - doesn't match member type
};

int main()
{
std::cout
<< "X: " << has_self<X>::value << std::endl
<< "Y: " << has_self<Y>::value << std::endl
<< "Z: " << has_self<Z>::value << std::endl
;
}

I must have missed something because now it would seem this does
what you want, at the time I thought it didn't which is why I
didn't respond, too much googling I guess.


I spent way too much time googling as well :-( ...

This code ICE's on gcc 3.4.0 as well but compiles on msc++ 7.1.

The last article by Rani Sharoni in the thread he shows an example that
ICE's on comeau. It seems Greg has fixed it and considers as valid code.

// reposted here fo googleability....
<code>
template<typename> struct Type2Type;

struct C { template<typename> struct B; };

template<typename T>
char* f3(Type2Type<typename T::B> *);

template<typename>
int* f3(...);

int* i2 = f3<C>(0);
// internal error: assertion failed at: "templates.c", line 6285
// no-longer ICE's as of at least 4.3.3
</code>

I modified this to:

<code>
template<typename> struct Type2Type;

struct C { struct B; };

template<typename T>
int f3(Type2Type<typename T::B> *);

template<typename>
char f3(...);

int i2 = sizeof( f3<C>(0) );

#include <iostream>
int main()
{
std::cout << i2;
}
</code>


I tried a similar thing last night and msvc and gcc complained while
comeau liked it. It does seem like this should compile as well. At
least we've moved away from ICE's...

<code>
typedef char MPT_False;
typedef int MPT_True;


template <unsigned int w_siz>
struct MPT_IntToType
{
typedef char type;
};

template <typename T1, typename T2>
MPT_True func( T2 ( T1::* )() );

template <typename w_D>
struct MPT_Finder_Member
{

template <typename w_T>
static MPT_True finder(
const w_T *,
typename MPT_IntToType<
sizeof( func( & w_T::Function ) )
::type * = 0
);

static MPT_False finder( const w_D * );

};

template <typename w_D >
struct MPT_ContainsFuncMember
{
struct DerivedClass : w_D
{
};

typedef DerivedClass * DerivedClassp;

enum {
value = (
sizeof( MPT_Finder_Member<w_D>::finder( DerivedClassp() ) )
== sizeof( MPT_True )
)
};

};


struct A
{
};

struct B
{
int Function();
};

// this works find so func<T1,T2> can be deduced
int x = sizeof( func( &B::Function ) );
int y = MPT_ContainsFuncMember<A>::value;
int z = MPT_ContainsFuncMember<B>::value;
</code>
 
G

Gianni Mariani

Gianni said:
Rob Williscroft wrote:
... ....

This code ICE's on gcc 3.4.0 as well but compiles on msc++ 7.1.

I take that back, it ICE's on 3.3.1, it runs fine on 3.4.0.
 
R

Rob Williscroft

Gianni Mariani wrote in in
comp.lang.c++:
I tried a similar thing last night and msvc and gcc complained while
comeau liked it. It does seem like this should compile as well. At
least we've moved away from ICE's...

Yes but CBuilderX (the only EDG frontend I have access too) gives
x,y,z as 4,0,0. What version of Comeau are you using, CBuilderX
gives __EDG_VERSION__ as 301.

In case you don't know, you can get CBuildeX from:

http://www.borland.com/products/downloads/download_cbuilderx.html

You need to download CBulderX personal and the Preview to get
your hands on the version 6.0 compiler.
<code>
typedef char MPT_False;
typedef int MPT_True;


template <unsigned int w_siz>
struct MPT_IntToType
{
typedef char type;
};

template <typename T1, typename T2>
MPT_True func( T2 ( T1::* )() );

I guess from this you want to be able to detect a member with *any*
return type, which my example didn't do ?
template <typename w_D>
struct MPT_Finder_Member
{

template <typename w_T>
static MPT_True finder(
const w_T *,
typename MPT_IntToType<
sizeof( func( & w_T::Function ) )
);

static MPT_False finder( const w_D * );

};

template <typename w_D >
struct MPT_ContainsFuncMember
{
struct DerivedClass : w_D
{
};

typedef DerivedClass * DerivedClassp;

enum {
value = (
sizeof( MPT_Finder_Member<w_D>::finder( DerivedClassp() ))
== sizeof( MPT_True )
)
};

};


struct A
{
};

struct B
{
int Function();
};

const int x = sizeof( func( &B::Function ) );
const int y = MPT_ContainsFuncMember<A>::value;
const int z = MPT_ContainsFuncMember<B>::value;

char assert_[ z != y ];

int main()
{
}

With the above both Comeau & Dinkumwares online compilers produce:

.... line 63: error: the size of an array must be greater than zero
char assert_[ z != y ];

Sorry that I've no explanation for why, AFAICT you code should work,
maybe you're ahead of your time :).

Rob.
 
G

Gianni Mariani

Rob said:
Gianni Mariani wrote in in
comp.lang.c++:




Yes but CBuilderX (the only EDG frontend I have access too) gives
x,y,z as 4,0,0. What version of Comeau are you using, CBuilderX
gives __EDG_VERSION__ as 301.

In case you don't know, you can get CBuildeX from:

http://www.borland.com/products/downloads/download_cbuilderx.html

You need to download CBulderX personal and the Preview to get
your hands on the version 6.0 compiler.

Thanks for the pointer !

....
I guess from this you want to be able to detect a member with *any*
return type, which my example didn't do ?

Yes. However I can live with the example you posted earlier.
....



const int x = sizeof( func( &B::Function ) );
const int y = MPT_ContainsFuncMember<A>::value;
const int z = MPT_ContainsFuncMember<B>::value;

char assert_[ z != y ];

int main()
{
}

With the above both Comeau & Dinkumwares online compilers produce:

... line 63: error: the size of an array must be greater than zero
char assert_[ z != y ];

Sorry that I've no explanation for why, AFAICT you code should work,
maybe you're ahead of your time :).

I've come across so many template bugs. Admitedly, they're more
difficult to find with the latest compilers but they are still
relatively easy to find.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,186
Latest member
vinaykumar_nevatia

Latest Threads

Top