"has member" detection using templates - why "." operator fails ?

Discussion in 'C++' started by Gianni Mariani, Apr 9, 2007.

  1. I'm hoping someone can tell me why using member address of works and why
    using the dot operator does not in the code below.

    The code below uses the template function resolution mechanism to
    determine wether a class contains a member. My understanding is that if
    a template function has an error during resolution of the function
    types, it is quietly eliminated from the resolution process. This can
    be used to detect things that would normally be an error to detect in
    regular code, namely checking for existance of a member. To get this
    mechanism to work, you need to contrive a class where you force the
    compiler at compile time to resolve which function to use but never
    actually call the function - sizeof comes to the aid. Each of the
    functions used can return a different sized object and the selection can
    proceed based on the size of the object that would be returned.

    So far so good.

    In my last attempt to do this, I noticed that no matter what I did, when
    I attempted to use the "." operator, the error was not silent. GCC as
    well as Comeau's try it out were not silent about function template
    resolution error when a "." operator was involved. However, taking the
    sizeof a pointer to member works as expected.

    The code is below. As posted it compiles under GCC (and I suspect
    comeau). I have not tested this on MSVC but if my experience a while
    back is any indication, it probably does not compile indicating a bug in
    MSVC.

    Why does the "." operator fail to compile in this case and the &T::
    succeed ?


    struct NoMemb { char a[1]; };
    struct Memb_MemberA { char a[2]; };
    struct Memb_MemberB { char a[3]; };

    template <typename T>
    struct InitObject
    {
    private:

    struct xA {};
    struct xB : xA {};

    template <int w_size>
    struct Detect
    {
    };

    public:

    // detect using sizeof( &T::membername )
    template <typename U>
    inline static Memb_MemberB ObjInitSel(
    U & obj, xB * b, Detect< sizeof(&U::MemberB) > * = 0
    );

    template <typename U>
    inline static Memb_MemberA ObjInitSel(
    U & obj, xB * b, Detect< sizeof(&U::MemberA) > * = 0
    );

    template <typename U>
    inline static NoMemb ObjInitSel( U & obj, xA * a );


    // detect using sizeof( T().membername )
    template <typename U>
    inline static Memb_MemberB ObjInitSelDot(
    U & obj, xB * b, Detect< sizeof(U().MemberB) > * = 0
    );

    template <typename U>
    inline static Memb_MemberA ObjInitSelDot(
    U & obj, xB * b, Detect< sizeof(U().MemberA) > * = 0
    );

    template <typename U>
    inline static NoMemb ObjInitSelDot( U & obj, xA * a );


    inline int ObjTest()
    {
    typedef xB * bp;

    T obj = T();

    int a = sizeof( ObjInitSel( obj, bp() ) );

    // uncomment line below to show the error using "."
    // a += sizeof( ObjInitSelDot( obj, bp() ) );

    return a;
    }
    };



    /////////// test code

    struct A
    {
    int a;
    char x[10];
    };


    struct B
    {
    int MemberA;
    char x[15];
    };


    struct C
    {
    int MemberB;
    char x[22];
    };

    int main()
    {
    InitObject<A>().ObjTest();
    InitObject<B>().ObjTest();
    InitObject<C>().ObjTest();
    }
     
    Gianni Mariani, Apr 9, 2007
    #1
    1. Advertising

  2. Re: "has member" detection using templates - why "." operator fails?

    * Gianni Mariani:
    >
    > I'm hoping someone can tell me why using member address of works and why
    > using the dot operator does not in the code below.
    >
    > The code below uses the template function resolution mechanism to
    > determine wether a class contains a member. My understanding is that if
    > a template function has an error during resolution of the function
    > types, it is quietly eliminated from the resolution process. This can
    > be used to detect things that would normally be an error to detect in
    > regular code, namely checking for existance of a member. To get this
    > mechanism to work, you need to contrive a class where you force the
    > compiler at compile time to resolve which function to use but never
    > actually call the function - sizeof comes to the aid. Each of the
    > functions used can return a different sized object and the selection can
    > proceed based on the size of the object that would be returned.
    >
    > So far so good.
    >
    > In my last attempt to do this, I noticed that no matter what I did, when
    > I attempted to use the "." operator, the error was not silent. GCC as
    > well as Comeau's try it out were not silent about function template
    > resolution error when a "." operator was involved. However, taking the
    > sizeof a pointer to member works as expected.
    >
    > The code is below. As posted it compiles under GCC (and I suspect
    > comeau). I have not tested this on MSVC but if my experience a while
    > back is any indication, it probably does not compile indicating a bug in
    > MSVC.


    With MSVC 7.1 moving the Detect structure to global scope helps a lot,
    but not for the ".".


    > Why does the "." operator fail to compile in this case and the &T::
    > succeed ?


    Compiles fine with Comeau Online. ;-)

    However, not with g++ 3.4.4 under Windows XP, and furthermore, changing
    "U().Method" to "((U*)0)->Method" ICEs the compiler:

    vc_project.cpp: In instantiation of `InitObject<A>':
    vc_project.cpp:91: instantiated from here
    vc_project.cpp:39: internal compiler error: Segmentation fault
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <URL:http://www.mingw.org/bugs.shtml> for instructions.

    I suggest you submit a full bug report.

    [code, snipped]

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Apr 9, 2007
    #2
    1. Advertising

  3. Re: "has member" detection using templates - why "." operator fails?

    Alf P. Steinbach wrote:
    ....
    > Compiles fine with Comeau Online. ;-)
    >
    > However, not with g++ 3.4.4 under Windows XP, and furthermore, changing
    > "U().Method" to "((U*)0)->Method" ICEs the compiler:
    >
    > vc_project.cpp: In instantiation of `InitObject<A>':
    > vc_project.cpp:91: instantiated from here
    > vc_project.cpp:39: internal compiler error: Segmentation fault
    > Please submit a full bug report,
    > with preprocessed source if appropriate.
    > See <URL:http://www.mingw.org/bugs.shtml> for instructions.
    >
    > I suggest you submit a full bug report.


    It does not ICE on g++ 4.1.1. (does ICE on g++ 4.0.0)

    It does compile fine with comeau. It looks like it's a bug in gcc.
     
    Gianni Mariani, Apr 9, 2007
    #3
  4. Re: "has member" detection using templates - why "." operator fails?

    Gianni Mariani wrote:
    ....
    > It does not ICE on g++ 4.1.1. (does ICE on g++ 4.0.0)
    >
    > It does compile fine with comeau. It looks like it's a bug in gcc.
    >


    GCC bug is here:
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31512
     
    Gianni Mariani, Apr 9, 2007
    #4
  5. Gianni Mariani

    Ron Natalie Guest

    Re: "has member" detection using templates - why "." operator fails?

    Alf P. Steinbach wrote:

    > However, not with g++ 3.4.4 under Windows XP, and furthermore, changing
    > "U().Method" to "((U*)0)->Method" ICEs the compiler:
    >

    While I'm sure that's not what the GCC guys intended, an internal
    compiler error is a valid response to invocation of undefined
    behavior :)
     
    Ron Natalie, Apr 9, 2007
    #5
  6. Re: "has member" detection using templates - why "." operator fails?

    * Ron Natalie:
    > Alf P. Steinbach wrote:
    >
    >> However, not with g++ 3.4.4 under Windows XP, and furthermore,
    >> changing "U().Method" to "((U*)0)->Method" ICEs the compiler:
    >>

    > While I'm sure that's not what the GCC guys intended, an internal
    > compiler error is a valid response to invocation of undefined
    > behavior :)


    Well, it's within a sizeof. But I agree that a case can be made that
    it's still UB. I've tried to make that case (didn't convince many).

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Apr 9, 2007
    #6
    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. work
    Replies:
    3
    Views:
    558
    P.Hill
    May 7, 2004
  2. JKop
    Replies:
    3
    Views:
    521
  3. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    979
    Mark Rae
    Dec 21, 2006
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,224
    Smokey Grindel
    Dec 2, 2006
  5. recover
    Replies:
    2
    Views:
    857
    recover
    Jul 25, 2006
Loading...

Share This Page