From: jamshid@ut-emx.uucp (Jamshid Afshar)
Newsgroups: comp.lang.c++
Subject: Re: Borland C++ 3.1 fails to conform to C++ Standard
Summary: 'huge' is not Standard C++
Keywords: C++ Standard
Date: 27 Jul 92 07:54:29 GMT
Reply-To: jamshid@emx.utexas.edu
Followup-To: comp.os.msdos.programmer
Organization: The University of Texas at Austin; Austin, Texas

As the crux of the problem is related to a common MS-DOS C/C++
compiler extension, I have redirected followups to
comp.os.msdos.programmer.

In article <j_ohearn.711991770@dn73> j_ohearn@dsg4.dse.beckman.com writes:
>class Vector
>{
>    double huge *data;

First, there is no Standard C++ yet.  Second, I'm sure it will not
contain the modifier 'huge', so it's not quite valid to claim Borland
is nonconforming because of a problem related to the use of that keyword.

>    public: [...]
>    double& operator()( unsigned long i ) {
>        return data[i - low]; //Line that offends ver 3.1 but compiled without
>    }                         //error under 3.0
>};

You declare operator() as returning a reference to a double.
Depending on which memory model you are compiling under, pointers and
references are assumed to be either 'near' or 'far' (never 'huge'; not
even in the huge memory model).  'data' is a 'huge' pointer so you are
actually returning a 'double huge&' from within operator().
Therefore, you're assigning a 'double huge&' to either a 'double
near&' (unsafe conversion) or a 'double far&' (safe, but still a
conversion).  According to the ARM 8.4.3, a non-const reference can
only be initialized by an object of the exact same type -- no
conversions are allowed.  Earlier C++ rules (which BC++ 3.0 implemented
with a warning) said that a temporary would be created and the
reference would be initialized to that.  Now only const references can
create a temporary.
	const double& d2 = 1;  // okay, temporary "1.0" generated
	double& d1 = 1;  // error, but earlier rules would generate temporary

Of course, how the above ARM rule applies to an MS-DOS extensions like
'huge'/'far'/'near' is up to the compiler maker (another good reason
not to use extensions), but BC++ 3.1's behavior does seem to be
consistent with the "standard" part of the language.

>Vector::Vector(unsigned long L, unsigned long H)
>{
>    low = L;
>    high = H;
>    data = new double huge[H - L + 1];

So that's how you get 'new' to allocate over 64K objects!  This is
analogous to farmalloc().  It calls Borland's
	void* operator new(unsigned long);
instead of
	void operator new(size_t);  // size_t is typedefed to an 'unsigned int'

>}
>
>The above class compiled and functioned successfully under version 3.0 
>but under version 3.1 I receive the error message:
>    "Reference initialized with 'double' requires lvalue of type 'double'"
>which referred to the line I have indicated in the above class listing.

Bad message; it should say something like "Reference initialized with
'huge double' requires lvalue of type 'near|far double'".

>This contains no syntax error that I am aware of and is essentially given 
>in various textbooks on C++ as a method for implementing 'safe arrays'.

Well, if you really need arrays over 64K, it's probably best that
you're using a Vector class (a template would be even better) instead
of polluting your code with 'huge'.  Everything should work fine if
you do something like:

#if __TINY__ || __SMALL__ || __MEDIUM__
#error My Vector class requires compact, large or huge memory model.
#endif
	double& operator(unsigned long i) {
	   return (double&)data[i-low];
	}

Just be careful that you don't try to iterate through an array >64K
with a regular pointer as only 'huge' pointers wrap correctly.
	Vector hugevec(MAX); ...
	for (double* d = &hugevec(0); d<=&hugevec(MAX-1); d++)  // BAD!
	
>Send any private responses to (I will make sure Jack gets them):
>j_ohearn@dsg4.dse.beckman.com

Okay.  Btw, I just noticed there's an operator new() patch for BC++
3.1 at Simtel in borland/bc31p1.zip (something about assertion errors
/ aborts).  See the comp.os.msdos.programmer FAQ if you don't know
about Simtel.  Also, Borland is supposed to release a DOS extender at
the end of the year, so hopefully we won't have to mess with 64K
limits for much longer.

Jamshid Afshar
jamshid@emx.utexas.edu