From 9bef93fc7cdc036c6fbedbffbf4eb14ddbe7a5c4 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 29 Sep 2000 22:22:37 +0000 Subject: [PATCH] hints on portability for Borland C++ [SVN r7877] --- more/borland_cpp.html | 362 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 more/borland_cpp.html 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 @@ + + + +Portability Hints: Borland C++ 5.5.1 + + + + + + + + + + + + + +
c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore
+ +

+ +

Portability Hints: Borland C++ 5.5.1

+ +It is a general aim for boost libraries to be +portable. The primary means +for achieving this goal is to adhere to ISO Standard C++. However, +ISO C++ is a broad and complex standard and most compilers are +not fully conformant to ISO C++ yet. In order to achieve portability +in the light of this restriction, it seems advisable to get acquainted +with those language features that some compilers do not fully +implement yet. +

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

Preprocessor symbol

+ +The preprocessor symbol __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 40x0540
Borland C++ Builder 50x0550
Borland C++ 5.50x0550
Borland C++ 5.5.10x0551
+ +

Core Language

+ +

[using-directive] Mixing using-declarations and +using-directives

+ +Mixing using-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 template] using-declarations for class +templates

+ +Identifiers for class templates can be used as arguments to +using-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 const arg] Deduction of constant arguments to function +templates

+ +Template function type deduction should omit top-level constness. +However, this code fragment instantiates "f<const int>(int)": + +
+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(int)"
+        (void) &y;
+}
+
+int main()
+{
+        const int i = 17;
+        f(i);
+}
+
+ +The boost/rational.hpp header exhibits this problem in connection with +the gcd() function. + + +

[function address] Resolving addresses of overloaded +functions

+ +Addresses of overloaded functions are not in all contexts properly +resolved (std:13.4 [over.over]); here is a small example: +
+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. + +

[string conversion] Converting const char * to +std::string

+ +Implicitly converting 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 value defaults] Dependent default arguments for template +value parameters

+ +Template value parameters which default to an expression dependent on +previous template parameters don't work: + +
+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). + + +

[function partial ordering] Partial ordering of function +templates

+ +Partial ordering of function templates, as described in std:14.5.5.2 +[temp.func.order], does not work: + +
+#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. + + +

Library

+ + +

[cmath.abs] Function double std::abs(double) +missing

+ +The function double 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. + +

Appendix: Additional issues with Borland C++ version 5.5

+ +These issues are documented mainly for historic reasons. If you are +still using Borland C++ version 5.5, you are strongly encouraged to +obtain an upgrade to version 5.5.1, which fixes the issues described +in this section. + +

[inline friend] Inline friend functions in template classes

+ +If a friend function of some class has not been declared before the +friend function declaration, the function is declared at the namespace +scope surrounding the class definition. Together with class templates +and inline definitions of friend functions, the code in the following +fragment should declare (and define) a non-template function "bool +N::f(int,int)", which is a friend of class N::A<int>. However, +Borland C++ v5.5 expects the function f to be declared beforehand: + +
+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]. + +

+ +


+ +2000-09-30 Jens Maurer + +