polkadot
asked on
problems with function pointers in Bloodshed DEV C++
Program is giving me trouble in Bloodshed DEV C++ but not in Visual Studio C++:
I created a custom String class and one of the methods is String::operator>.
In a friend class I want to have this function pointer:
int ( String::*compare_op )( const String ) const;
compare_op = String::operator>;
but it gives me the error
187 C:\Dev-Cpp\main.cpp invalid use of non-static member function `int String::operator>(String) const'
187 C:\Dev-Cpp\main.cpp cannot convert `int (String::)(String) const' to `int (String::*)(String) const' in assignment
I created a custom String class and one of the methods is String::operator>.
In a friend class I want to have this function pointer:
int ( String::*compare_op )( const String ) const;
compare_op = String::operator>;
but it gives me the error
187 C:\Dev-Cpp\main.cpp invalid use of non-static member function `int String::operator>(String) const'
187 C:\Dev-Cpp\main.cpp cannot convert `int (String::)(String) const' to `int (String::*)(String) const' in assignment
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> compare_op = &String::operator>;
That should indeed fix it ... (no points for me please - just confirming)
That should indeed fix it ... (no points for me please - just confirming)
ASKER
compare_op = &String::operator>; ???
but why the difference between compilers?
but why the difference between compilers?
>> but why the difference between compilers?
Some compilers are more strict than others.
compare_op = &String::operator>;
is the only correct (read : portable) way to do it.
Some compilers are more strict than others.
compare_op = &String::operator>;
is the only correct (read : portable) way to do it.
>>is the only correct (read : portable) way to do it.
Both methods are correct, in accordance with the C++ standard.
However, some compilers incorrectly only recognize one method.
The VC++ 7.1 and 8.0 compiler, are more in compliance with the standard then the GNU 3.x compiler. Dev C++ uses the GNU compiler.
You might want to consider switching to GNU 4.x compiler. It might be more portable.
Both methods are correct, in accordance with the C++ standard.
However, some compilers incorrectly only recognize one method.
The VC++ 7.1 and 8.0 compiler, are more in compliance with the standard then the GNU 3.x compiler. Dev C++ uses the GNU compiler.
You might want to consider switching to GNU 4.x compiler. It might be more portable.
>> Both methods are correct, in accordance with the C++ standard.
Can you show that in the standard ? As far as I know the standard, for pointers to member functions you NEED to fully qualify with the class qualification and the & like so :
compare_op = &String::operator>;
It seems that VC++ accepts this too :
compare_op = String::operator>;
but that's only because it's more loose on syntax than prescribed by the standard.
If you can show me otherwise in the standard, then please do :)
Can you show that in the standard ? As far as I know the standard, for pointers to member functions you NEED to fully qualify with the class qualification and the & like so :
compare_op = &String::operator>;
It seems that VC++ accepts this too :
compare_op = String::operator>;
but that's only because it's more loose on syntax than prescribed by the standard.
If you can show me otherwise in the standard, then please do :)
>>If you can show me otherwise in the standard, then please do :)
See section 4.3 of the C++ standard.
See section 4.3 of the C++ standard.
Actually, I just realize this section has a footnote, and the footnote states that the rule doesn't apply to nonstatic member functions.
So if String::operator> is not a static member function, then you're correct, in that it should have the &.
For static member functions, and global functions, you don't need the &.
So it would seem that in this case, the GNU compiler is more in compliance.
So if String::operator> is not a static member function, then you're correct, in that it should have the &.
For static member functions, and global functions, you don't need the &.
So it would seem that in this case, the GNU compiler is more in compliance.
>> See section 4.3 of the C++ standard.
That's a pointer-to-function, not a pointer-to-member. Check 5.3.1.
That's a pointer-to-function, not a pointer-to-member. Check 5.3.1.
>>That's a pointer-to-function, not a pointer-to-member. Check 5.3.1.
It also applies to pointer to a member function. Otherwise, there would be no point in having a foot-note for the non-static member functions.
It also applies to pointer to a member function. Otherwise, there would be no point in having a foot-note for the non-static member functions.
oops - forgot to refresh the page before posting :)
>>Check 5.3.1.
Exactly what part of 5.3.1?
Exactly what part of 5.3.1?
I believe you're referring to 5.3.1 sub section 3, which is referring to non-static member function.
>> It also applies to pointer to a member function.
Afaik, the standard uses pointer-to-member to refer to non-static member functions, and use pointer-to-function for all static functions and static member functions. In any case, that's what I meant when I used pointer-to-member.
Let me see if I can find something about that ... ok : 13.4 subsection 3
>> I believe you're referring to 5.3.1 sub section 3, which is referring to non-static member function.
Yep.
Afaik, the standard uses pointer-to-member to refer to non-static member functions, and use pointer-to-function for all static functions and static member functions. In any case, that's what I meant when I used pointer-to-member.
Let me see if I can find something about that ... ok : 13.4 subsection 3
>> I believe you're referring to 5.3.1 sub section 3, which is referring to non-static member function.
Yep.
>> Let me see if I can find something about that ... ok : 13.4 subsection 3
Or better yet : 8.3.3 subsection 3
Or better yet : 8.3.3 subsection 3
polkadot, is your problem solved? Does it compile with the & ?
>>>>> invalid use of non-static member function `int String::operator>(String) const'
Actually a compare function passed normally is a global function or a static member function. You could make your operator> a global function by defining it
class String
{
...
friend bool operator>(const String& s1, const String& s2)
{
return stricmp(s1.pstr, s2.pstr) > 0;
}
With that it is a global function and you shouldn't get errors when assigning it at neither platform.
You also could omit passing a compare function at all. However, then you have to provide a built-in operator< (not operator>) in String class like that
class String
{
...
public:
bool operator<(const String& s) const
{
return stricmp(s1.pstr, s2.pstr) < 0;
}
...
};
Regards, Alex
>>>>> invalid use of non-static member function `int String::operator>(String) const'
Actually a compare function passed normally is a global function or a static member function. You could make your operator> a global function by defining it
class String
{
...
friend bool operator>(const String& s1, const String& s2)
{
return stricmp(s1.pstr, s2.pstr) > 0;
}
With that it is a global function and you shouldn't get errors when assigning it at neither platform.
You also could omit passing a compare function at all. However, then you have to provide a built-in operator< (not operator>) in String class like that
class String
{
...
public:
bool operator<(const String& s) const
{
return stricmp(s1.pstr, s2.pstr) < 0;
}
...
};
Regards, Alex
ASKER
nope, I don't care what the standard is, I want to know how to make it work in this compiler: Bloodshed Dev C++, its supposed to be just windows gui over g++ (i think)
here is the code:
#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class String {
char* str; // data member -- private
int len; // actual
public:
enum SortOrder { Asc, Desc };
enum ErrorsIO { ReadFail, WriteFail };
// constructors-destructor
String(); // default constructor
String( const String& ); // copy constructor
String( const int ); // string initialized to blanks
String( const char* ); // from a C string, char*
~String(); // destructor
// other methods as functions
int write();
int write( FILE* );
int read();
int read( FILE* );
// operators
String operator+( const String& ) const;
int operator<( const String ) const;
int operator>( const String ) const;
String& operator=( const String& );
// friends
friend void sort( String*, int, int ); // selection sort
};
#endif // StringHeaderLoaded_Version _1_0
//The following is stings.cpp
// default constructor -- create empty string
String::String()
{
str = new char[ 1 ]; // allocate
*str = '\0'; // initialize to null string
len = 0;
}
// convert constructor
String::String( const char* cstr )
{
// +1 to ensure room for null terminator
str = new char[ strlen( cstr ) + 1 ];
strcpy( str, cstr );
len = strlen( str );
}
// copy constructor -- String ==> String
String::String( const String& strarg )
{
// copy an existing String.str into a new
// one after first allocating sufficient storage
strcpy( str = new char[ strarg.len + 1 ],
strarg.str );
len = strarg.len;
}
// blank string constructor
String::String( const int lenarg )
{
str = new char[ lenarg + 1 ];
len = lenarg;
char* ptr = str;
for ( int i = 0; i < len; i++ )
*ptr++ = ' ';
*ptr = '\0'; // null terminate
}
// destructor -- deallocate storage
String::~String()
{
delete[ ] str;
}
// write String to standard output
// with a terminating newline
int String::write()
{
return printf( "%s\n", str );
}
// write String to specified file
int String::write( FILE* outfile )
{
if ( !outfile )
return WriteFail;
else
return fprintf( outfile, "%s\n", str );
}
// read String from standard input
int String::read()
{
scanf( "%s", str );
return len = strlen( str );
}
// read String from designated file
int String::read( FILE* infile )
{
if ( !infile )
return ReadFail;
else {
fscanf( infile, "%s", str );
return len = strlen( str );
}
}
// assignment operator
String& String::operator=( const String& strarg )
{
// check whether String assigned to itself
if ( this != &strarg ) {
delete[ ] str; // free current storage
len = strarg.len;
str = new char[ len + 1 ]; // allocate new storage
strcpy( str, strarg.str ); // copy contents
}
return *this;
}
// < operator for less than comparisons
int String::operator<( const String strarg ) const
{
return strcmp( str, strarg.str ) < 0;
}
// > operator for greater than comparisons
int String::operator>( const String strarg ) const
{
return strcmp( str, strarg.str ) > 0;
}
// + operator for concatenations
String String::operator+( const String& strarg ) const
{
// allocate enough storage for 2 strings + '\0'
char* temp = new char[ len + strarg.len + 1 ];
// copy 1st string and concatenate second
strcpy( temp, str );
strcat( temp, strarg.str );
// define a variable of type String to be
// used as a return value
String retval( temp );
// free temporary storage
delete[ ] temp;
return retval;
}
// selection sort an array of String
void sort( String a[ ], int size, int order )
{
int next;
// set comparison operator based on order parm
int ( String::*compare_op )( const String ) const;
compare_op = String::operator>;
//
// ( order == String::Asc ) ? String::operator< :
// String::operator>;
// loop thru array, picking biggest or smallest
// element each time, depending on sort order
for ( int i = 0; i < size - 1; i++ ) {
next = i; // assume ith String smallest-biggest
// compare against remaining elements
for ( int j = i + 1; j < size; j++ )
if ( ( a[ j ].*compare_op )( a[ next ] ) )
next = j;
// put smallest-biggest at position i
if ( i != next ) {
String temp = a[ i ];
a[ i ] = a[ next ];
a[ next ] = temp;
}
}
}
int main()
{
String x("okdcba");
return 0;
}
here is the code:
#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class String {
char* str; // data member -- private
int len; // actual
public:
enum SortOrder { Asc, Desc };
enum ErrorsIO { ReadFail, WriteFail };
// constructors-destructor
String(); // default constructor
String( const String& ); // copy constructor
String( const int ); // string initialized to blanks
String( const char* ); // from a C string, char*
~String(); // destructor
// other methods as functions
int write();
int write( FILE* );
int read();
int read( FILE* );
// operators
String operator+( const String& ) const;
int operator<( const String ) const;
int operator>( const String ) const;
String& operator=( const String& );
// friends
friend void sort( String*, int, int ); // selection sort
};
#endif // StringHeaderLoaded_Version
//The following is stings.cpp
// default constructor -- create empty string
String::String()
{
str = new char[ 1 ]; // allocate
*str = '\0'; // initialize to null string
len = 0;
}
// convert constructor
String::String( const char* cstr )
{
// +1 to ensure room for null terminator
str = new char[ strlen( cstr ) + 1 ];
strcpy( str, cstr );
len = strlen( str );
}
// copy constructor -- String ==> String
String::String( const String& strarg )
{
// copy an existing String.str into a new
// one after first allocating sufficient storage
strcpy( str = new char[ strarg.len + 1 ],
strarg.str );
len = strarg.len;
}
// blank string constructor
String::String( const int lenarg )
{
str = new char[ lenarg + 1 ];
len = lenarg;
char* ptr = str;
for ( int i = 0; i < len; i++ )
*ptr++ = ' ';
*ptr = '\0'; // null terminate
}
// destructor -- deallocate storage
String::~String()
{
delete[ ] str;
}
// write String to standard output
// with a terminating newline
int String::write()
{
return printf( "%s\n", str );
}
// write String to specified file
int String::write( FILE* outfile )
{
if ( !outfile )
return WriteFail;
else
return fprintf( outfile, "%s\n", str );
}
// read String from standard input
int String::read()
{
scanf( "%s", str );
return len = strlen( str );
}
// read String from designated file
int String::read( FILE* infile )
{
if ( !infile )
return ReadFail;
else {
fscanf( infile, "%s", str );
return len = strlen( str );
}
}
// assignment operator
String& String::operator=( const String& strarg )
{
// check whether String assigned to itself
if ( this != &strarg ) {
delete[ ] str; // free current storage
len = strarg.len;
str = new char[ len + 1 ]; // allocate new storage
strcpy( str, strarg.str ); // copy contents
}
return *this;
}
// < operator for less than comparisons
int String::operator<( const String strarg ) const
{
return strcmp( str, strarg.str ) < 0;
}
// > operator for greater than comparisons
int String::operator>( const String strarg ) const
{
return strcmp( str, strarg.str ) > 0;
}
// + operator for concatenations
String String::operator+( const String& strarg ) const
{
// allocate enough storage for 2 strings + '\0'
char* temp = new char[ len + strarg.len + 1 ];
// copy 1st string and concatenate second
strcpy( temp, str );
strcat( temp, strarg.str );
// define a variable of type String to be
// used as a return value
String retval( temp );
// free temporary storage
delete[ ] temp;
return retval;
}
// selection sort an array of String
void sort( String a[ ], int size, int order )
{
int next;
// set comparison operator based on order parm
int ( String::*compare_op )( const String ) const;
compare_op = String::operator>;
//
// ( order == String::Asc ) ? String::operator< :
// String::operator>;
// loop thru array, picking biggest or smallest
// element each time, depending on sort order
for ( int i = 0; i < size - 1; i++ ) {
next = i; // assume ith String smallest-biggest
// compare against remaining elements
for ( int j = i + 1; j < size; j++ )
if ( ( a[ j ].*compare_op )( a[ next ] ) )
next = j;
// put smallest-biggest at position i
if ( i != next ) {
String temp = a[ i ];
a[ i ] = a[ next ];
a[ next ] = temp;
}
}
}
int main()
{
String x("okdcba");
return 0;
}
ASKER
compare_op = &String::operator>;
works, thanks
works, thanks
>> nope, I don't care what the standard is
Well, you're in luck :) The solution you used also follows the standard - so you are ok for both Dev-C++ AND the standard now :)
Well, you're in luck :) The solution you used also follows the standard - so you are ok for both Dev-C++ AND the standard now :)
Post the String class declaration, and the function that's assigning the function pointer.