Solved

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

Posted on 2004-10-21
9
2,637 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
ID: 12367961
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
ID: 12367973
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
ID: 12367976
'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
ID: 12368006
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 19

Author Comment

by:mrwad99
ID: 12368042
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
ID: 12368657
>>> /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
ID: 12368710
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
ID: 12368928
>>>> 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
ID: 12369182
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

911 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

18 Experts available now in Live!

Get 1:1 Help Now