Link to home
Start Free TrialLog in
Avatar of polkadot
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
Avatar of Axter
Axter
Flag of United States of America image

Please post more of your code.

Post the String class declaration, and the function that's assigning the function pointer.
ASKER CERTIFIED SOLUTION
Avatar of efn
efn

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> compare_op = &String::operator>;

That should indeed fix it ... (no points for me please - just confirming)
Avatar of polkadot
polkadot

ASKER

compare_op = &String::operator>; ???

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.
>>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.

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.
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.
>> 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.

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?
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.
>> Let me see if I can find something about that ... ok : 13.4 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

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;
}
 


compare_op = &String::operator>;

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 :)