Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > SFINAE compilation troubles

Reply
Thread Tools

SFINAE compilation troubles

 
 
justin.adam.miller@gmail.com
Guest
Posts: n/a
 
      02-03-2005
I've been trying to use the sfinae principle in some code and have been
getting many compiler errors. So I decided to try a very simplified
version to see if I had the idea correct. Here's the example:

#include <iostream>

template <typename T>
class IsClassT
{
private:
typedef char One;
typedef struct { char a[2]; } Two;
template <typename C> static One test(int C::*);
template <typename C> static Two test(...);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};

class A
{
public:
int a;
};

int main()
{
using namespace std;

if(IsClassT<A>::Yes)
cout << "A is a class!" << endl;
if(IsClassT<A*>::Yes)
cout << "A* is a class too!" << endl;

return 0;
}

This you may recognize is copied DIRECTLY from "C++ Templates" by
Josuttis, at least the template part anyway.

This is supposed to work right? Why does it think it can't find the
"test" function? It looks like the compiler isn't matching either of
those overloads. Also, as neither of those "test" functions are
actually being called (sizeof doesn't actually call the function), code
doesn't need to be provided for them.

Please, any help would be GREATLY appreciated!! Posted below are the
error messages I got when compiling with g++ 3.2.2 and 3.4.2.

With g++ 3.2.2

sfinae.cxx:5: warning: all member functions in class `IsClassT<T>' are
private
sfinae.cxx: In instantiation of `IsClassT<A>':
sfinae.cxx:26: instantiated from here
sfinae.cxx:26: no method `IsClassT<A>::test<A>'
sfinae.cxx:26: enumerator value for `Yes' not integer constant
sfinae.cxx: In instantiation of `IsClassT<A*>':
sfinae.cxx:28: instantiated from here
sfinae.cxx:28: no method `IsClassT<A*>::test<A*>'
sfinae.cxx:28: enumerator value for `Yes' not integer constant

With g++ 3.4.2:

sfinae.cxx:12: error: expected primary-expression before '>' token
sfinae.cxx: In instantiation of `IsClassT<A>':
sfinae.cxx:26: instantiated from here
sfinae.cxx:12: error: enumerator value for `Yes' not integer constant
sfinae.cxx: In instantiation of `IsClassT<A*>':
sfinae.cxx:28: instantiated from here
sfinae.cxx:12: error: enumerator value for `Yes' not integer constant

 
Reply With Quote
 
 
 
 
Attila Feher
Guest
Posts: n/a
 
      02-04-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
[SNIP]
> template <typename T>
> class IsClassT
> {
> private:
> typedef char One;
> typedef struct { char a[2]; } Two;
> template <typename C> static One test(int C::*);
> template <typename C> static Two test(...);
> public:
> enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
> enum { No = !Yes };
> };

[SNIP]
> Josuttis, at least the template part anyway.

[SNIP]

I was able to "fix" it this way:
enum { Yes = sizeof(IsClassT<T>::template test<T>(0)) == 1 };
Note the template keyword before the test function name. I am not sure it
is needed there, I have guessed that somehow g++ does not understand that
IsClassT<T>::test is a template name.

Comeau online compiles it both ways, which is weird. I suggest you look
around on the books' web for the errata, you may find a comment there
explaining the problem of g++.

Attila


 
Reply With Quote
 
 
 
 
justin.adam.miller@gmail.com
Guest
Posts: n/a
 
      02-04-2005
Thanks so much for the response.

Your fix does indeed compile fine with 3.4.2, but not with 3.2.2. Is
this simply a compiler bug that was fixed somewhere between
3.2.2-3.4.2?

Oddly enough, that code now compiles on the Sun compiler v6U2. It
doesn't work according to the standard however. IsClassT<A>::Yes
returns false. It seems to match the (...) version of test before the
one with the pointer to a member. Not the first bug I've found in Sun's
compiler (at least the earlier versions anyway).

Justin

 
Reply With Quote
 
Attila Feher
Guest
Posts: n/a
 
      02-08-2005
(E-Mail Removed) wrote:
> Thanks so much for the response.
>
> Your fix does indeed compile fine with 3.4.2, but not with 3.2.2. Is
> this simply a compiler bug that was fixed somewhere between
> 3.2.2-3.4.2?


I have no idea. I am inclined to suspect that it is rather 3.4.2 which
is at fault, but I only base my quess on what Comeau does in strict mode.
Of course this can be some sort of corner case, as Comeau accepts both forms
(the one with and without the template keyword).

As for the differences betweem 3.2.2 and 3.4.2, I think (but I may be wrong)
that 3.4.2 has a new C++ parser and has also introduced two phase name
lookup for templates. Any of those two is good enough cause for such a
change in behavior.

> Oddly enough, that code now compiles on the Sun compiler v6U2. It
> doesn't work according to the standard however. IsClassT<A>::Yes
> returns false. It seems to match the (...) version of test before the
> one with the pointer to a member. Not the first bug I've found in
> Sun's compiler (at least the earlier versions anyway).


What I know as error in v6u2 was an error introduced in the 6 series, a name
mangling problem with function signatures containing const arguments passed
by value. The template support is better with v6, but it has its little
problems, so some things just won't compile (or work).

--
Attila aka WW


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
confused with SFINAE Dilip C++ 1 07-06-2006 09:35 PM
SFINAE kaalus@gmail.com C++ 4 04-26-2006 02:08 PM
SFINAE problem. christopher diggins C++ 4 09-26-2005 06:25 PM
Using SFINAE with constructors Clark S. Cox III C++ 2 09-09-2005 09:34 PM
problem with SFINAE applied to class methods Peter Collingbourne C++ 8 07-04-2004 07:25 PM



Advertisments