C++ porting between MS VC++ 5.0 (NT/'95) and SunOS Solaris 4.2 version 1.8, Aug 26, 1998 Igor Markov, Max Moroz and Mike Oliver Maintainers: mmoroz@ucla.edu, imarkov@ucla.edu Copyright, 1998 ABKGroup (UCLA/CS) and the Regents of the University of California ------------------------------------------------------------------------------ These notes collect our experience in designing and maintaining C++ code good both for Solaris CC 4.2 and Windows NT/'95 MS VC++ 5.0 If you use different versions of the compilers, some of the below may not apply. If your compiler(s) are newer, seek an update of this document by emailing to the maintainers. (1) To designate compiler-specific code, use #ifdef _MSC_VER ... #end to check for MS VC++; and #ifdef __SUNPRO_CC ... #end to check for SunPro C++. (2) MS VC++ preprocessor often ignores filename capitalisation. For example, if you say #include "Graphs.h" MS VC++ will include either "graphs.h" or "Graphs.h". SunOS CC, will only include "Graphs.h". (3) MS VC++ offers both old- and new-style headers (e.g. and ). The new-style headers make use of namespaces and provide much better standard conformance (i.e. old-style headers in MS VC++ are wildly buggy). Solaris CC, as of version 4.2 does not support namespaces, thus no new-style headers; however, there were no complaint regarding the standard conformance in its old-style headers. The old- and the new-style headers (e.g. in MS VC++) are mutually exclusive : one can not include both types in user headers, and one must not link user codes which use old and new-style headers. (4) Specific oddities about the old-style headers in MS VC++. In the example char buffer[10000]; cin>>buffer; If the first character the user types in is CTRL-Z, end-of-file is *not* reported. Moreover, if the next characters are, say, 'x' and , the cin>>buffer will set buff to "x". If the next character is just or another CTRL-Z, the cin returns end-of-file condition. Please let me know if anyone figures the complete rules behind this behaviour. (6) In MS VC++, when using erase from a const iterator, you have to const_cast (mro's adaptation of DB/dbPostProc.cxx code) #ifndef _MSC_VER design._nets.erase(nItr, design.netsEnd()); #else design._nets.erase(const_cast(nItr), const_cast(design.netsEnd())); #endif ilm : why exactly is this needed ? (8) Some old-style headers are named slightly differently on CC and VC++: on MS VC++ on SunOS CC Note the 8.3-character filename truncation. (9) SunOS CC has an Error: Cannot return a reference to a local variable or temporary. MS VC++ does not report any errors on the same code (Max, can you add a verified example of this ?) msm: does it keep the temporary long enough? what does the Standard require here? (10) Files that are fine in Windows need an extra linebreak at the end to compile in UNIX. Otherwise: // File a.h #ifdef A_H #define A_H // stuff ... #endif //END OF FILE HERE (no new line at end of this line) // File a.cxx #include a.h #include b.h // Oops! Preprocessor outputs: #endif #include b.h Error results since everything on the same line as #endif is ignored. (11) Many useful warnings/errors from CC are absent in MS VC++. In MS VC++ (a) no warning about hiding (rather than overriding) a virtual method -- such code often needs correction, even if only for code clarity. Similarly about hiding a variable or non-virtual method. (b) no way to trace a template error to the code where the template was instantiated (c) but instead LOTS of useless warnings are spewed out. Turn them off with respective #pragma statements. (12) Many new C++ features present in MS VC++ are absent in SunOS CC: (a) namespaces (b) type bool (but STL defines it) (c) default template parameters (d) non-type (i.e. value) template parameters for functions (however, SunCC 4.2 allows to parametrize classes by values) (13) MSVC++ does not allow some constructions that SunOS allows. E.g. (a) the example void *ptr; // ... void *ptr1 (ptr); // error won't compile --- requires declarator (*ptr1) in parens: void (*ptr1) (ptr); (b) if you have class T, you will sometimes need to typedef things like T&, T*, const T&, const T* etc. For example, inline ostream& operator<<(//... is not allowed and (ostream&) needs to be parenthesized or typedefed. CC4.2 does not like parens here, so typedefing is the only sensible solition (#defining is just _bad ;-) (c) Definitions of global inline functions were seen to require a semicolon after the closing curly brace. (14) The format in which MSVC++ prints doubles is different. This almost guarantees your Solaris regression tests to fail. "Ported" regression scripts for MS VC++ must be maintained. (15) Order of evaluation (not that "of use") of "arguments" in cout << arg1 << arg2 << arg3; is "left to right" with CC4.2 and "right to left" on MSVC++5.0 This does not change the order in which the arguments appear in cout, but was enough to fail a regression test where one of the arguments was returned from a function call with a side effect of changing a variable being printed in the same line of code. msm: This looks like non-standard compliant to me on the part of MS VC; but I am not sure. (16) does not exist and is not needed for MS VC++ 5.0 (zero length file seems to cure problems). We have added this file to ABKCommon (17) In bit-fields, MS VC++ requires unsigned char, while char works fine for SunPro CC. MS VC++ loses one bit if a char is used. (18) SunCC 4.2 is more conservative in using implicit conversions than MSVC++ 5.0 The following code compiles with MS VC++ 5.0, but needs an explicit cast to compile on SunCC 4.2 template BFS(Graph& g, int root); main() { // ... ARigidGraph rg; ARigidGraph::NodeIter it; BFS(rg, it); // does not compile } Here ARigidGraph::NodeIter type has implicit conversion to integer. It is enough for MS VC++ to find the BFS template function; but not enough for SunOS. SunOS compiles this code only with BFS(rg, static_cast(it)); (19) To check for Solaris version, here is the suggestion from Usenet: compile with -DSOLARIS_VERSION="\"`uname -r`\"". Not recommended, though, due to inflexibility and ugliness. Each feature supposedly can be checked directly by its own #ifdef CHANGES [previous version is at Portability.1] mm 980826: checked wiuth new patches for Solaris removed section (5), (7) added section (19) slight changes in wording