CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    overloading operation for inner class of class template

    Hi!

    I have a problem compiling the following code:

    Code:
    #include <iostream>
    
    using namespace std;
    
    
    
    
    
    template <typename T>
    class Some_class
    {
        public:
    
            class Inner;
    
    };
    
    
    
    
    
    template <typename T>
    class Some_class<T>::Inner
    {
        public:
    
            T member;
    };
    
    
    
    
    
    //----------------------------------------------------------------------------
    
    template <typename T>
    bool operator != ( typename const Some_class<T>::Inner &a,
                       typename const Some_class<T>::Inner &b
                     )
    {
        return ( a.member != b.member );
    }
    
    
    
    
    
    //----------------------------------------------------------------------------
    
    int main( void )
    {
        Some_class<int>::Inner x, y;
    
        x.member = 1;
        y.member = 2;
    
        cout << (x != y) << endl;
    }
    Particularly, operator != causes some errors (with g++):

    tempcmp.cpp:37: error: declaration of `operator!=' as non-function
    tempcmp.cpp:37: error: expected nested-name-specifier before "const"
    tempcmp.cpp:37: error: expected identifier before "const"
    tempcmp.cpp:37: error: expected `(' before "const"
    tempcmp.cpp:38: error: expected nested-name-specifier before "const"
    tempcmp.cpp:38: error: expected identifier before "const"
    tempcmp.cpp:38: error: expected `(' before "const"
    tempcmp.cpp:40: error: expected `;' before '{' token
    tempcmp.cpp: In function `int main()':
    tempcmp.cpp:57: error: no match for 'operator!=' in 'x != y'

    This is a simplified version of a much complex code. That one was tested on MS Visual C++ 2005 Express. So it doesn't seem to be a compiler issue.


    I could implement != as Inner's member. But in this case, how could I proceed expressions like:

    <some int> != <some Inner>

    ?

    Note that <some Inner> != <some int> does work if Inner's constructor Inner( int ) is implemented. But vice versa (<some int> != <some Inner>) does not!

  2. #2
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: overloading operation for inner class of class template

    One set of errors could probably be eliminated by proper placement of typename, e.g., changing this:
    Code:
    typename const Some_class<T>::Inner &
    to
    Code:
    const typename Some_class<T>::Inner &
    or
    Code:
    typename Some_class<T>::Inner const &
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  3. #3
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    Re: overloading operation for inner class of class template

    Thank's that helped. But now I've got another problem: error: no match for 'operator!=' in 'x != y'
    even though
    Code:
    template <typename T>
    bool operator != ( const typename Some_class<T>::Inner &a,
                       const typename Some_class<T>::Inner &b
                     )
    {
        return ( a.member != b.member );
    }
    is defined...

  4. #4
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    Re: overloading operation for inner class of class template

    Just now I've tested my code in MS Visual C++ 2005 Express. It shows a number of intersections with library names.

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: overloading operation for inner class of class template

    Quote Originally Posted by andrey_zh View Post
    Just now I've tested my code in MS Visual C++ 2005 Express. It shows a number of intersections with library names.
    The reason why your code didn't compile is that template functions are not considered matches to your operator !=.

    This compiles:
    Code:
    bool operator != (const typename Some_class<int>::Inner& a,
                      const typename
    Some_class<int>::Inner& b
                     ) 
    {
        return ( a.member != b.member );
    }
    If operator != were made a member of the class, then you may have more luck (for example, see how std::vector implements its operator !=).

    Regards,

    Paul McKenzie

  6. #6
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    Re: overloading operation for inner class of class template

    This copiles:


    Could someone evaluate my code? I.e. style and so on.
    Is there a better way (less complex or more traditional or sth else) to do this stuff?
    To Paul McKenzie: Thanks, but I need a "generic solution" in terms of generic programming, not just a single function.

    Code:
    #include <iostream>
    
    using namespace std;
    
    
    
    
    
    template <typename T>
    class Some_class
    {
        public:
    
            class Inner;
    
    };
    
    
    
    
    
    template <typename T>
    class Some_class<T>::Inner
    {
        public:
    
            Inner( void ) { member = 0; }
    
            Inner( int value ) { member = value; }
    
            const Inner &operator = ( const Inner &r )
            {
                if ( this != &r )
                {
                    member = r.member;
                }
    
                return *this;
            }
    
            bool operator != ( const Inner &r )  { return ( member != r.member ); } // general
            bool operator != ( T r )             { return ( member != r ); } // to get rid of constructor call = "type cast"
    
            T member;
    
    };
    
    
    
    
    
    //----------------------------------------------------------------------------
    
    template <typename T>
    bool operator != ( T lhr,
                       const typename Some_class<T>::Inner &rhr
                      )
    {
        return ( lhr != rhr.member );
    }
    
    
    
    
    
    //----------------------------------------------------------------------------
    
    int main( void )
    {
        Some_class<int>::Inner x, y;
    
        x.member = 1;
        y.member = 2;
    
        cout << ( x != y ) << endl;
        cout << ( x != 5 ) << endl;
        cout << ( 5 != y ) << endl; // doen't compile without standalone operator != <int> ( int, Some_class<int>::Inner )
    }
    Last edited by andrey_zh; April 9th, 2009 at 04:47 PM.

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: overloading operation for inner class of class template

    Quote Originally Posted by andrey_zh View Post
    To Paul McKenzie: Thanks, but I need a "generic solution" in terms of generic programming, not just a single function.
    I already stated to look how std::vector implements their operators.

    As a matter of fact, it would be wise to see how other classes that have already been developed overload their operators.

    As to your code,

    1) There is no need for a user-defined assignment operator.

    2) Use the initialization list in the constructor instead of assignment within the constructor body.

    3) Your class will fall flat on its face if T were a std::string. The constructor alone would cause problems.

    Regards,

    Paul McKenzie

  8. #8
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    Re: overloading operation for inner class of class template

    Thanks, but I'm only interested in binary operator != overloading.

    Other code is only for demonstration purposes, that's why member 'member' is left public.

  9. #9
    Join Date
    Apr 1999
    Posts
    27,449

    Re: overloading operation for inner class of class template

    Quote Originally Posted by andrey_zh View Post
    Thanks, but I'm only interested in binary operator != overloading.
    That last code does compile on the Comeau compiler.

    What version of g++ are you using? Always mention the version of the compiler, not just the compiler name.

    Other code is only for demonstration purposes, that's why member 'member' is left public.
    I don't know why you bring that up. No one mentioned anything about the member being public. What I mentioned in my previous post is that if T were a std::string, the code would probably compile but possibly crash. As a matter of fact, if T were any type where it doesn't know how to assign a 0 to it, the template won't compile.

    Regards,

    Paul McKenzie

  10. #10
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Re: overloading operation for inner class of class template

    From your code, we can clearly see that you are not fully understand basic C++ language features and progress to advance C++.

    Instead of initialize member to zero, try initialize using generic approach.
    Thanks for your help.

  11. #11
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    Re: overloading operation for inner class of class template

    1) Unfortuatelly, I was forced to install a very old Dev-C++ to have the same tool as we use at the University. g++ comes with it. So with the shame I have to quote:

    g++ (GCC) 3.4.2 (mingw-special)
    Copyright (C) 2004 Free Software Foundation, Inc.

    It's 2009 AD now, so soon I'll move it to a virtual machine to clear my PATH variable for something newer.

    Also I work with MS Visual C++ 2005, BCC 5.5.1 and a very nostalgic Borland C++ 3.1 ( I like last two ones and proudly can say that I can and like work from the command line and hate Dev-C++ interface )

    2) Under 'public member' I also assumed stuff like stupid names for classes and "member = 0"; I know last two are not 'public members'!

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

    The only thing I'm interested in now, is proper overloading of binary operators for Inner classes.

    Code:
    Inner::operator != ( T stuff )
    and
    Code:
    <global namespace>::operator != ( T stuff, const Some_stuff<T>::Inner &rhr )
    looks a little bit asymmetrical.

    P.S.
    The last thing compiles with MS Visual C++ 2005 (with minor modification).
    Last edited by andrey_zh; April 12th, 2009 at 05:37 PM. Reason: :smile insted of ::operator

  12. #12
    Join Date
    Apr 1999
    Posts
    27,449

    Re: overloading operation for inner class of class template

    Quote Originally Posted by andrey_zh View Post
    1) Unfortuatelly, I was forced to install a very old Dev-C++ to have the same tool as we use at the University. g++ comes with it. So with the shame I have to quote:

    g++ (GCC) 3.4.2 (mingw-special)
    Copyright (C) 2004 Free Software Foundation, Inc.
    As pointed out, your original code compiles correctly with the Comeau compiler, and will probably compile using gcc 4.x.
    Also I work with MS Visual C++ 2005, BCC 5.5.1 and a very nostalgic Borland C++ 3.1 ( I like last two ones and proudly can say that I can and like work from the command line and hate Dev-C++ interface )
    Whenever you use templates, it requires you to use an up to date C++ compiler. Otherwise you'll end up wasting time trying to implement the unimplementable. That's why many vendors of third-party code refuse to support certain compilers -- these older compilers can't handle the modern, but valid, template code.

    Regards,

    Paul McKenzie

  13. #13
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    Re: overloading operation for inner class of class template

    So could someone tell me about fast (avoiding convertions), proper (both in style and syntax, not just compile) way to overload != in this case?

  14. #14
    Join Date
    Apr 1999
    Posts
    27,449

    Re: overloading operation for inner class of class template

    Quote Originally Posted by andrey_zh View Post
    So could someone tell me about fast (avoiding convertions), proper (both in style and syntax, not just compile) way to overload != in this case?
    What is the real problem you really are trying to solve? Maybe there is a much better approach than having inner classes and overloading their operators.

    Regards,

    Paul McKenzie

  15. #15
    Join Date
    Mar 2009
    Location
    Riga, Latvia
    Posts
    128

    Re: overloading operation for inner class of class template

    May be someone remembers this thread: http://www.codeguru.com/forum/showthread.php?t=472965
    I'm still fighting with my Singly-linked list. It's implemented via a class template. I'll reproduce the backbone of the class "by heart":

    Code:
    template <typename T>
    class Slist
    {
        public:
            class Iterator;
    
        private:
            class Node;
            class Head;
            class Data;
    };

    All main operators of Iterator i.e. ->, *, [], both ++(void) prefix and ++(int) postfix forms are already implemented.

    The very first node is a so called "sentinel" - dummy node not containing any data. So I have two ways to run through the list

    Code:
    Slist<some_type>::Iterator it = slist.get_head();
    (1) already works fine
    Code:
    while ( it++ != slit.get_last() )
    {
        // treat node here
    }
    and

    (2) I want to get
    Code:
    while ( ++it != 0 )
    {
        // treat node here
    }
    which is almost equal to
    Code:
    while ( 0 != ++it ) //it even seems me that some people prefer this form
    {
        // treat node here
    }
    Note: the very last node is not a sentinel node, it simply has next_node = 0.

    ++
    has the following somewhere inside
    Code:
    if ( node != 0 )
    {
        node = node->next_node;
    }
    'node' is a member of an Iterator of course.

    It's well known, that prefix form of ++ is more natural and fast. So I want to trade some more CPU cycles by avoiding constructor call and terrible user interface respectively:

    ++it != 0, which actually is: ++it != Slist<some_type>::Iterator(0)

    and

    Slist<some_type>::Iterator(0) != ++it // explicitly

    the only good alternative is to have:

    != ( const Node *lhr, const Iterator &rhr )
    != ( const Iterator &lhr, const Node *rhr )

    but the only working solution found (see posts above) doesn't look beautiful (IMHO). Or it's OK? I'm ready to change my opinion if someone self-confidently tells me that it is...
    Last edited by andrey_zh; April 16th, 2009 at 03:28 PM.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured