diff --git a/more/borland_cpp.html b/more/borland_cpp.html new file mode 100644 index 0000000000..bb2b1efe70 --- /dev/null +++ b/more/borland_cpp.html @@ -0,0 +1,362 @@ + +
+ +![]() |
+ Home | +Libraries | +People | +FAQ | +More | +
+ +
+ +This page gives portability hints on some language features of the +Borland C++ version 5.5.1 compiler. Furthermore, the appendix +presents additional problems with Borland C++ version 5.5. Borland +C++ 5.5.1 is a freely available command-line compiler for Win32 +available at +http://www.borland.com/. +
+ +Each entry in the following list describes a particular issue, +complete with sample source code to demonstrate the effect. +Most sample code herein has been verified to compile with gcc 2.95.2 +and Comeau C++ 4.2.44. + + +
__BORLANDC__
is defined for all
+Borland C++ compilers. Its value is the version number of the
+compiler interpreted as a hexadecimal number. The following table
+lists some known values.
++ +
Compiler | +__BORLANDC__ value |
+
---|---|
Borland C++ Builder 4 | +0x0540 | +
Borland C++ Builder 5 | +0x0550 | +
Borland C++ 5.5 | +0x0550 | +
Borland C++ 5.5.1 | +0x0551 | +
using
-declarations and
+using
-directivesusing
-directives (which refer to whole namespaces)
+and namespace-level using
-declarations (which refer to
+individual identifiers within foreign namespaces) causes ambiguities
+where there are none. The following code fragment illustrates this:
+
++namespace N { + int x(); +} + +using N::x; +using namespace N; + +int main() +{ + &x; // Ambiguous overload +} ++ + +
using
-declarations for class
+templatesusing
-declarations as any other identifier. However, the
+following code fails to compile with Borland C++:
+
++template<class T> +class X { }; + +namespace N +{ + // "cannot use template 'X+ + +' without specifying specialization parameters" + using ::X; +}; +
+template<class T> +void f(T x) +{ + x = 1; // works + (void) &x; + T y = 17; + y = 20; // "Cannot modify a const object in function f+ +The boost/rational.hpp header exhibits this problem in connection with +the gcd() function. + + +(int)" + (void) &y; +} + +int main() +{ + const int i = 17; + f(i); +} +
+template<class Arg> +void f( void(*g)(Arg) ); + +void h(int); +void h(double); + +template<class T> +void h2(T); + +int main() +{ + void (*p)(int) = h; // this works (std:13.4-1.1) + void (*p2)(unsigned char) = h2; // this works as well (std:13.4-1.1) + f<int>(h2); // this also works (std:13.4-1.3) + + // "Cannot generate template specialization from h(int)", + // "Could not find a match for f<Arg>(void (*)(int))" + f<double>(h); // should work (std:13.4-1.3) + + f( (void(*)(double))h); // C-style cast works (std:13.4-1.6 with 5.4) + + // "Overloaded 'h' ambiguous in this context" + f(static_cast<void(*)(double)>(h)); // should work (std:13.4-1.6 with 5.2.9) +} ++ +Workaround: Always use C-style casts when determining +addresses of (potentially) overloaded functions. + +
const char *
to
+std::string
const char *
parameters to
+std::string
arguments fails if template functions are
+explicitly instantiated (it works in the usual cases, though):
+
++#include <string> + +template<class T> +void f(const std::string & s) +{} + +int main() +{ + f<double>("hello"); // "Could not find a match for f<T>(char *)" +} + ++ +Workaround: Avoid explicit template function +instantiations (they have significant problems with Microsoft Visual +C++) and pass default-constructed unused dummy arguments with the +appropriate type. Alternatively, if you wish to keep to the explicit +instantiation, you could use an explicit conversion to +
std::string
or declare the template function as taking a
+const char *
parameter.
+
+
++template<class T> +struct A +{ + static const bool value = true; +}; + +// "Templates must be classes or functions", "Declaration syntax error" +template<class T, bool v = A<T>::value> +struct B {}; + +int main() +{ + B<int> x; +} + ++ + +Workaround: If the relevant non-type template +parameter is an implementation detail, use inheritance and a fully +qualified identifier (for example, ::N::A<T>::value). + + +
+#include <iostream> + +template<class T> struct A {}; + +template<class T1> +void f(const A<T1> &) +{ + std::cout << "f(const A<T1>&)\n"; +} + +template<class T> +void f(T) +{ + std::cout << "f(T)\n"; +} + +int main() +{ + A<double> a; + f(a); // output: f(T) (wrong) + f(1); // output: f(T) (correct) +} ++ +Workaround: Declare all such functions uniformly as +either taking a value or a reference parameter. + + +
double std::abs(double)
+missingdouble std::abs(double)
should be defined
+(std:26.5-5 [lib.c.math]), but it is not:
+
++#include <cmath> + +int main() +{ + double (*p)(double) = std::abs; // error +} ++ +Note that
int std::abs(int)
will be used without warning
+if you write std::abs(5.1)
.
+
+Similar remarks apply to seemingly all of the other standard math
+functions, where Borland C++ fails to provide float
and
+long double
overloads.
+
+Workaround: Use std::fabs
instead if
+type genericity is not required.
+
+
+namespace N { +template<class T> +class A +{ + // "f is not a member of 'N' in function main()" + friend bool f(T x, T y) { return x < y; } +}; +} + +int main() +{ + N::A<int> a; +} ++ +This technique is extensively used in boost/operators.hpp. Giving in +to the wish of the compiler doesn't work in this case, because then +the "instantiate one template, get lots of helper functions at +namespace scope" approach doesn't work anymore. Defining +BOOST_NO_OPERATORS_IN_NAMESPACE (a define +BOOST_NO_INLINE_FRIENDS_IN_CLASS_TEMPLATES would match this case +better) works around this problem and leads to another one, see +[using-template]. + +
+ +