Solved

Error C2065: 'max' : undeclared identifier - why ?

Posted on 2004-10-21
9
2,559 Views
Last Modified: 2008-01-09
Ah hello.

I cannot get the code at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcstdlib/html/vclrfalgorithmmax.asp to compile, regardless of adding the stated /EHsc flag.  Constant error message is

error C2065: 'max' : undeclared identifier

what am I doing wrong ?  I have scoured the web looking at every result bought back but cannot get rid of this.  

There is probably a fundamental mistake being made, but since I have never come across it before I do not know how to resolve it...:)

TIA
0
Comment
Question by:mrwad99
  • 4
  • 4
9 Comments
 
LVL 12

Expert Comment

by:stefan73
Comment Utility
Hi mrwad99,
Since you didn't post the source, I can only guess.

The type of template functions is declared implicitly by the arguments, so you don't need:

my maxint = <int> max(myint1,myint2);

but can write
my maxint = max(myint1,myint2);


Make sure that the two types you compare are the same. In case of comparing classes, make sure you have the appropriate operator (probably < ) defined, or better define a binary predicate - comparing instances of "Person" by "<" doesn't make much sense semantically, for example.

Cheers!

Stefan
0
 
LVL 19

Author Comment

by:mrwad99
Comment Utility
Hi Stefan,

thanks for that reply.  The source follows from the link I posted.  I would doubt that MS made a mistake in the code that they published, but maybe they have...

// alg_max.cpp
// compile with: /EHsc
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
#include <ostream>

using namespace std;
class CInt;
ostream& operator<<( ostream& osIn, const CInt& rhs );

class CInt
{
public:
   CInt( int n = 0 ) : m_nVal( n ){}
   CInt( const CInt& rhs ) : m_nVal( rhs.m_nVal ){}
   CInt&   operator=( const CInt& rhs ) {m_nVal =
   rhs.m_nVal; return *this;}
   bool operator<( const CInt& rhs ) const
      {return ( m_nVal < rhs.m_nVal );}
   friend ostream& operator<<( ostream& osIn, const CInt& rhs );

private:
   int m_nVal;
};

inline ostream& operator<<( ostream& osIn, const CInt& rhs )
{
   osIn << "CInt( " << rhs.m_nVal << " )";
   return osIn;
}

// Return whether modulus of elem1 is greater than modulus of elem2
bool mod_greater ( int elem1, int elem2 )
{
   if ( elem1 < 0 )
      elem1 = - elem1;
   if ( elem2 < 0 )
      elem2 = - elem2;
   return elem1 > elem2;
};

int main( )
{
   // Comparing integers directly using the max algorithm
   int a = 6, b = -7, c = 7;
   const int& result1 = max ( a, b, mod_greater );
   const int& result2 = max ( b, c );

   cout << "The mod_greater of the integers 6 & -7 is: "
        << result1 << "." << endl;
   cout << "The larger of the integers -7 & 7 is: "
        << result2 << "." << endl;
   cout << endl;

   // Comparing set containers with elements of type CInt
   // using the max algorithm
   CInt c1 = 1, c2 = 2, c3 = 3;
   set<CInt> s1, s2, s3;
   set<CInt>::iterator s1_Iter, s2_Iter, s3_Iter;
   
   s1.insert ( c1 );
   s1.insert ( c2 );
   s2.insert ( c2 );
   s2.insert ( c3 );

   cout << "s1 = (";
   for ( s1_Iter = s1.begin( ); s1_Iter != --s1.end( ); s1_Iter++ )
      cout << " " << *s1_Iter << ",";
   s1_Iter = --s1.end( );
   cout << " " << *s1_Iter << " )." << endl;

   cout << "s2 = (";
   for ( s2_Iter = s2.begin( ); s2_Iter != --s2.end( ); s2_Iter++ )
      cout << " " << *s2_Iter << ",";
   s2_Iter = --s2.end( );
   cout << " " << *s2_Iter << " )." << endl;

   s3 = max ( s1, s2 );
   cout << "s3 = max ( s1, s2 ) = (";
   for ( s3_Iter = s3.begin( ); s3_Iter != --s3.end( ); s3_Iter++ )
      cout << " " << *s3_Iter << ",";
   s3_Iter = --s3.end( );
   cout << " " << *s3_Iter << " )." << endl << endl;

   // Comparing vectors with integer elements using the max algorithm
   vector <int> v1, v2, v3, v4, v5;
   vector <int>::iterator Iter1, Iter2, Iter3, Iter4, Iter5;

   int i;
   for ( i = 0 ; i <= 2 ; i++ )
   {
      v1.push_back( i );
   }

   int ii;
   for ( ii = 0 ; ii <= 2 ; ii++ )
   {
      v2.push_back( ii );
   }

   int iii;
   for ( iii = 0 ; iii <= 2 ; iii++ )
   {
      v3.push_back( 2 * iii );
   }
   
   cout << "Vector v1 is ( " ;
   for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
      cout << *Iter1 << " ";
   cout << ")." << endl;

   cout << "Vector v2 is ( " ;
   for ( Iter2 = v2.begin( ) ; Iter2 != v2.end( ) ; Iter2++ )
      cout << *Iter2 << " ";
   cout << ")." << endl;
   
   cout << "Vector v3 is ( " ;
   for ( Iter3 = v3.begin( ) ; Iter3 != v3.end( ) ; Iter3++ )
      cout << *Iter3 << " ";
   cout << ")." << endl;

   v4 = max ( v1, v2 );
   v5 = max ( v1, v3 );

   cout << "Vector v4 = max (v1,v2) is ( " ;
   for ( Iter4 = v4.begin( ) ; Iter4 != v4.end( ) ; Iter4++ )
      cout << *Iter4 << " ";
   cout << ")." << endl;

   cout << "Vector v5 = max (v1,v3) is ( " ;
   for ( Iter5 = v5.begin( ) ; Iter5 != v5.end( ) ; Iter5++ )
      cout << *Iter5 << " ";
   cout << ")." << endl;
}

TIA
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 100 total points
Comment Utility
'max' is a function that is either implemented by a macro in WINDEF.H

  #define max(a, b) ((a) < (b))? (b) : (a)

or by a template function of STL in include file <algorithm>.

To avoid problems because of that Microsoft gives this hint:

Microsoft-Specific:
To avoid conflicts with min and max in WINDEF.H, use _MIN and _MAX instead. These macros evaluate to _cpp_min and _cpp_max, respectively.
END Microsoft-Specific

So, either replace max by _MAX - as recommended - or add a define statement

#define max _cpp_max

or use _cpp_max instead of max.

Regards, Alex



0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
The macro solution in WINDEF.H is not recommended as it fails in some cases:

    int m = max(rand(), 100);   // the macro calls rand() twice, so the max return is most likely wrong
    int m  = max(i, ++j);         // j gets incremented twice

Regards, Alex
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 19

Author Comment

by:mrwad99
Comment Utility
Ah,

right.  So essentially there are two solutions,

(1) do the MS thing with _MAX, or

(2) don't use the STL max, use the WINDEF.h one ?

And the former is the best idea for reasons you have stated.

Ok.....

Regarding that code, what is the /EHsc flag all about, and why does MS not state there and then to do the stuff you have mentioned with _MAX ?  Was it an ommision or can thie code compile as is anyhow ?

Thanks Alex.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>> /EHsc

that compiler flag is only for exception handling. It doesn't help with 'max' declaration

MSDN:
--------------------------------------------------------------------------------------------
EH{s|a}[c][-]

This option specifies the model of exception handling to be used by the compiler.

Use /EHs to specify the synchronous exception handling model.


Use /EHa to specify the asynchronous exception handling model.
The /EHc option requires that /EHs, /EHa, or /GX is specified. It tells the compiler to assume that extern C functions never throw an exception.

The option can be cleared by the symbol &#8220;-&#8221;. For example: /EHsc- is interpreted as /EHs /EHc- , and is equivalent to /EHs.
------------------------------------ end MSDN -----------------------------------------------------------------

>>> why does MS not state there and then to do the stuff you have mentioned with _MAX

That's a Bill's question, isn't it? The link from above is a newer doc coming with Visual .Net 2003. Maybe it doesn't care much about problems when using older code samples or older versions of Visual Studio.

>> Was it an ommision or can thie code compile as is anyhow ?

When using STL that came with VC6, there is no template function max but only _cpp_max. Newer STL versions may be different. With VC6 you either have to use _cpp_max or _MAX or define max as a macro or a template function yourself. If you want to get the code compiled by not making changes to the code itself, you may add a macro to your project settings (C++ Tab - Preprocessor - Preprocessor definitions) (separate it by comma ',')

    max=_cpp_max

However, you shouldn't need windef.h if you do so.

Regards, Alex









Regards, Alex
0
 
LVL 19

Author Comment

by:mrwad99
Comment Utility
Yeah that is fine; I use the replacement macro

#define max _cpp_max

as suggested and all works fine.

>> However, you shouldn't need windef.h if you do so.

Interestingly, whenever I #include <WINDEF.H> I get compile errors in that, but that is past the scope of this question and the main issue has been resolved.

Thanks a lot Alex, I appreciate it :)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> whenever I #include <WINDEF.H> I get compile errors

windef.h defines max as

   #define max(a, b) ((a) < (b))? (b) : (a)

that doesn't compile if max got replaced by _cpp_max  (a function cannot be redefined by a macro). However, you can do that:

#ifdef max
#define max_save max
#undef max
#endif

#include  <windef.h>

#ifdef max_save
#define max max_save
#undef max_save
#endif

not very elegant ... but should work .... (sometimes Precompiled Header files won't work with that .. )

Regards, Alex


0
 
LVL 19

Author Comment

by:mrwad99
Comment Utility
Thanks for that Alex; the compile errors are still there but when that becomes a problem I will raise this issue again.

If you do find a solution, please post it and I will award a further 100 points, but it not no problem.  The original question has been answered :)
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now