We help IT Professionals succeed at work.

problems with function pointers in Bloodshed DEV C++

polkadot
polkadot asked
on
850 Views
Last Modified: 2013-12-14
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
Comment
Watch Question

AxterSenior Software Engineer
CERTIFIED EXPERT

Commented:
Please post more of your code.

Post the String class declaration, and the function that's assigning the function pointer.
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
CERTIFIED EXPERT
Top Expert 2009

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

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

Author

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

but why the difference between compilers?
CERTIFIED EXPERT
Top Expert 2009

Commented:
>> 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.
AxterSenior Software Engineer
CERTIFIED EXPERT

Commented:
>>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.
CERTIFIED EXPERT
Top Expert 2009

Commented:
>> 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 :)
AxterSenior Software Engineer
CERTIFIED EXPERT

Commented:
>>If you can show me otherwise in the standard, then please do :)

See section 4.3 of the C++ standard.
AxterSenior Software Engineer
CERTIFIED EXPERT

Commented:
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.
CERTIFIED EXPERT
Top Expert 2009

Commented:
>> See section 4.3 of the C++ standard.

That's a pointer-to-function, not a pointer-to-member. Check 5.3.1.
AxterSenior Software Engineer
CERTIFIED EXPERT

Commented:
>>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.
CERTIFIED EXPERT
Top Expert 2009

Commented:
oops - forgot to refresh the page before posting :)
AxterSenior Software Engineer
CERTIFIED EXPERT

Commented:
>>Check 5.3.1.

Exactly what part of 5.3.1?
AxterSenior Software Engineer
CERTIFIED EXPERT

Commented:
I believe you're referring to 5.3.1 sub section 3, which is referring to non-static member function.
CERTIFIED EXPERT
Top Expert 2009

Commented:
>> 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.
CERTIFIED EXPERT
Top Expert 2009

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

Author

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


Author

Commented:
compare_op = &String::operator>;

works, thanks
CERTIFIED EXPERT
Top Expert 2009

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

Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.