RAD Studio
ContentsIndex
PreviousUpNext
Stricter C++ Compiler: Binding of References and Qualifiers

There are many constructs that now generate error messages from the CodeGear C++ compiler included with C++Builder 2007 and newer releases. The rules governing this behavior are described in section 8.5.3 of the 2003 C++ ANSI standard.  

The rules can be divided into the following categories (with the compiler switch that overrides this behavior):

  • Binding a non-const lvalue to to non-const reference. (Use the compiler switch -Vbr to allow this.)
  • Binding a temporary to a non-const reference. (Use the compiler switch -Vbr to allow this.)
  • Binding of const or volatile objects to non-const or non-volatile methods repectively. (Use the compiler switch -Vbn to allow this.)
Previous versions of the Borland C++ compilers allowed various forms of binding to non-const reference parameters. In the following example, for instance, one was allowed to simply cast the psize parameter:

int takesLongRef(long& l);

  int takesUnsignedPtr(unsigned long* psize) {

     return takesLongRef((long)*psize);
  }

With C++Builder2007, the above code generates these errors:

Error E2357 test.cpp 3: Reference initialized with 'long', needs lvalue of type 'long' in function takesUnsignedPtr(unsigned long *)  

 

Error E2342 test.cpp 3: Type mismatch in parameter 'l' (wanted 'long &', got 'long') in function takesUnsignedPtr(unsigned long *)

To remedy this, you can cast psize before dereferencing, as in:

int takesLongRef(long& l);    
int takesUnsignedPtr(unsigned long* psize) {     return takesLongRef(*reinterpret_cast <long*>(psize));   }

Be aware of cases that involve temporaries in unobvious ways. For example, some binary operators imply a temporary:

enum { zero, one, two } num;     
num |= two; // Not allowed    
num = num | two; // OK 

Another case that involves temporaries in an unobvious way is the return value of a property. The following example illustrates code that compiled with previous versions of the compiler:

#include <vcl.h> 

class TTest {   
   WideString FData ;   
public:  
   __property WideString Data = {read = FData };   
};    

void Func(WideString& wref);    

void test() { 
   TTest t;  
   Func(t.Data);   
}

With C++Builder 2007, the above generates two errors:

Error E2357 test.cpp 14: Reference initialized with 'const WideString', needs lvalue of type 'WideString' in function test()   

 

Error E2342 test.cpp 14: Type mismatch in parameter 'wref' (wanted 'WideString &', got 'WideString') in function test()  

You can fix this by changing the reference to a const reference, as in:  

void Func(const WideString& wref);  

Here is an example of trying to bind a const object to a non-const method:

struct X {  
   void foo();   
};   
const X x;   
x.foo(); //error

The temporaries and references issue referred to above is encountered in code generated by previous versions of the Reconcile Error Dialog Wizard.  

To remedy this, look for the VarToAnsiStr method:

AnsiString VarToAnsiStr (Variant &V TFieldType DataType) 

and change it to take a const Variant&, as in:

AnsiString VarToAnsiStr (const Variant &V, TFieldType DataType)  
Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!