By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,413 Members | 999 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,413 IT Pros & Developers. It's quick & easy.

is this code valid ?

P: n/a

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<w_T*>(0)->Function()) // magic here *****
// sizeof(w_T().Function()) // other magic that does same
::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
]
Jul 22 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Gianni Mariani wrote in news:c8********@dispatch.concentric.net 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=e...dm=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.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #2

P: n/a
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=e...dm=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>
Jul 22 '05 #3

P: n/a
Gianni Mariani wrote:
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.

Jul 22 '05 #4

P: n/a
Gianni Mariani wrote in news:c8********@dispatch.concentric.net 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/down...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 ) )
>::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();
};


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.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #5

P: n/a
Rob Williscroft wrote:
Gianni Mariani wrote in news:c8********@dispatch.concentric.net 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/down...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.


Jul 22 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.