Solved

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

Posted on 2004-10-21
9
2,837 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

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

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
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…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

738 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