SFINAE compilation troubles

Discussion in 'C++' started by justin.adam.miller@gmail.com, Feb 3, 2005.

  1. Guest

    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
    , Feb 3, 2005
    #1
    1. Advertising

  2. Attila Feher Guest

    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
    Attila Feher, Feb 4, 2005
    #2
    1. Advertising

  3. Guest

    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
    , Feb 4, 2005
    #3
  4. Attila Feher Guest

    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
    Attila Feher, Feb 8, 2005
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Collingbourne

    problem with SFINAE applied to class methods

    Peter Collingbourne, Jul 1, 2004, in forum: C++
    Replies:
    8
    Views:
    448
    Pete Becker
    Jul 4, 2004
  2. Clark S. Cox III

    Using SFINAE with constructors

    Clark S. Cox III, Sep 9, 2005, in forum: C++
    Replies:
    2
    Views:
    368
    Howard Hinnant
    Sep 9, 2005
  3. christopher diggins

    SFINAE problem.

    christopher diggins, Sep 26, 2005, in forum: C++
    Replies:
    4
    Views:
    447
    christopher diggins
    Sep 26, 2005
  4. SFINAE

    , Apr 26, 2006, in forum: C++
    Replies:
    4
    Views:
    461
    n2xssvv g02gfr12930
    Apr 26, 2006
  5. Dilip

    confused with SFINAE

    Dilip, Jul 6, 2006, in forum: C++
    Replies:
    1
    Views:
    323
    Victor Bazarov
    Jul 6, 2006
Loading...

Share This Page