|
-
April 9th, 2009, 02:02 PM
#1
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!
-
April 9th, 2009, 02:19 PM
#2
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 &
-
April 9th, 2009, 02:51 PM
#3
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...
-
April 9th, 2009, 03:02 PM
#4
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.
-
April 9th, 2009, 03:16 PM
#5
Re: overloading operation for inner class of class template
 Originally Posted by andrey_zh
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
-
April 9th, 2009, 03:40 PM
#6
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.
-
April 9th, 2009, 06:57 PM
#7
Re: overloading operation for inner class of class template
 Originally Posted by andrey_zh
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
-
April 10th, 2009, 05:37 AM
#8
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.
-
April 10th, 2009, 06:31 AM
#9
Re: overloading operation for inner class of class template
 Originally Posted by andrey_zh
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
-
April 10th, 2009, 09:43 AM
#10
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.
-
April 12th, 2009, 05:35 PM
#11
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
-
April 12th, 2009, 09:56 PM
#12
Re: overloading operation for inner class of class template
 Originally Posted by andrey_zh
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
-
April 15th, 2009, 04:24 PM
#13
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?
-
April 15th, 2009, 05:40 PM
#14
Re: overloading operation for inner class of class template
 Originally Posted by andrey_zh
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
-
April 16th, 2009, 03:17 PM
#15
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.
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|