(setq-default indent-tabs-mode nil)Microsoft Visual C++ users should do the following:
Choose: Tools -- Options -- Tabs Then Set: "Tab size" to 8 and "Indent size" to 2, and indent using spaces.
(setq-default nuke-trailing-whitespace-p t)
-?
command line argument, are
provided to the program.
main
function must
always be declared with arguments, e.g.,
int main (int argc, char *argv[]) { [...] return 0; }
If you don't use the argc
and/or argv
arguments, don't declare them, e.g.,
int main (int, char *[]) { [...] return 0; }
Please declare the second argument as char *[]
instead of char **
. Ancient versions of MSC
complained about char **
; I've never seen a
C++ compiler complain about char *[]
.
main
must also return 0 on successful
termination, and non-zero otherwise.
// $Id$It is not necessary to fill in the fields of the keyword string, or modify them when you edit a file that already has one. CVS does that automatically when you checkout or update the file.
To insert that string at the top of a file:
perl -pi -e \ 'if (! $o) {printf "// \$Id\$\n\n";}; $o = 1;' file
#endif
with a /* */
C-style comment. It
should correspond to the condition in the matching
#if
directive. For example,
#if defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) # include /**/ <synch.h> # include /**/ <thread.h> # define ACE_SCOPE_PROCESS P_PID # define ACE_SCOPE_LWP P_LWPID # define ACE_SCOPE_THREAD (ACE_SCOPE_LWP + 1) # else # define ACE_SCOPE_PROCESS 0 # define ACE_SCOPE_LWP 1 # define ACE_SCOPE_THREAD 2 # endif /* ACE_HAS_STHREADS */ #endif /* ACE_HAS_THREADS */
char * /* foo */
instead of
char */*foo*/
. MS VC++
complains otherwise.
/**/
between an
#include
and
filename
, as shown in the above
example. This avoids dependency problems with Visual C++.
ACE_
or TAO_
. There are too many system headers out
there that #define OK
, SUCCESS
,
ERROR
, index
, s_type
,
and so on.
#if __FreeBSD__ < 3will evaluate true on any platform where __FreeBSD__ is not defined. The correct way to write that guard is:
#if defined (__FreeBSD__) && __FreeBSD__ < 3
#ifdefs
with typedefs
and #defines
. For example, use this:
#if defined(ACE_PSOS) typedef long ACE_NETIF_TYPE; # define ACE_DEFAULT_NETIF 0 #else /* ! ACE_PSOS */ typedef const TCHAR* ACE_NETIF_TYPE; # define ACE_DEFAULT_NETIF ASYS_TEXT("le0") #endif /* ! ACE_PSOS */
instead of:
#if defined (ACE_PSOS) // pSOS supports numbers, not names for network interfaces long net_if, #else /* ! ACE_PSOS */ const TCHAR *net_if, #endif /* ! ACE_PSOS */
#ifndef FOO_H #define FOO_H [contents of header file] #endif /* FOO_H */
This exact construct (note the #ifndef
)
is optimized by many compilers such they only open the
file once per compilation unit. Thanks to Eric C. Newton
<[email protected]> for pointing that out.
If the header #includes
an ACE library header,
then it's a good idea to include the #pragma once
directive:
#ifndef FOO_H #define FOO_H #include "ace/ACE.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ [contents of header file] #endif /* FOO_H */
#pragma once
must be protected, because some
compilers complain about it. The protection depends on
ACE_LACKS_PRAGMA_ONCE
, which is defined in
some ACE config headers. Therefore, the protected
#pragma once
construct should only be used after
an #include
of an ACE library header. Note that
many compilers enable the optimization if the #ifndef
protection construct is used, so for them, #pragma once
is superfluous.
No code can appear after the final
#endif
for the optimization to be effective and
correct.
Files that contain parametric classes should follow this style:
#ifndef FOO_T_H #define FOO_T_H #include "ace/ACE.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ // Put your template declarations here... #if defined (__ACE_INLINE__) #include "Foo_T.i" #endif /* __ACE_INLINE__ */ #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) #include "Foo_T.cpp" #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation "Foo_T.cpp" #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ #endif /* FOO_T_H */
Notice that some compilers need to see the code of the template,
hence the .cpp
file must be included from the
header file.
To avoid multiple inclusions of the .cpp
file it
should also be protected as in:
#ifndef FOO_T_C #define FOO_T_C #include "Foo_T.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #if !defined (__ACE_INLINE__) #include "ace/Foo_T.i" #endif /* __ACE_INLINE__ */ ACE_RCSID(lib, Foo_T, "$Id$") // put your template code here #endif /* FOO_T_H */
Finally, you may want to include the template header file from a
non-template header file (check
$ACE_ROOT/ace/Synch.h
); in such a case the template
header should be included after the inline
function definitions, as in:
#ifndef FOO_H #define FOO_H #include "ace/ACE.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ // Put your non-template declarations here... #if defined (__ACE_INLINE__) #include "Foo.i" #endif /* __ACE_INLINE__ */ #include "Foo_T.h" #endif /* FOO_H */
#include <math.h>
if at all possible.
The /usr/include/math.h
on SunOS 5.5.1 through 5.7
defines a struct name exception, which complicates
use of exceptions.
.cpp
file always include the corresponding
header file first, like this:
// This is Foo.cpp #include "Foo.h" #include "tao/Bar.h" #include "ace/Baz.h" // Here comes the Foo.cpp code....
In this way we are sure that the header file is self-contained and can be safely included from some place else.
<corba.h>
, this file should only be included
by the user and introduces cyclic dependencies in the library
that we must avoid.
for
loops should look like:
for (u_int i = 0; i < count; ++i) ++total;Though, I prefer to always wrap the body of the loop in braces, to avoid surprises when other code or debugging statements are added, and to maintain sanity when the body consists of a macro, such as an ACE_ASSERT without a trailing semicolon:
for (u_int i = 0; i < count; ++i) { ACE_ASSERT (++total < UINT_MAX;) }
Similarly, if
statements should have
a space after the ``if'', and no spaces just after
the opening parenthesis and just before the closing parenthesis.
size_t i = 0; for (size_t j = 0; file_name [j] != '\0'; ++i, ++j) { if (file_name [j] == '\\' && file_name [j + 1] == '\\') ++j; file_name [i] = file_name [j]; } // Terminate this string. file_name [i] = '\0';
Therefore, use this idiom for iterators, with prefix operator on the loop index:
ACE_Ordered_MultiSet<int> set; ACE_Ordered_MultiSet_Iterator<int> iter(set); for (i = -10; i < 10; ++i) set.insert (2 * i + 1);rather than the postfix operator:
for (i = -10; i < 10; i++) set.insert (2 * i + 1);
.i
file. That file is conditionally included by both the
.h
file, for example:
class ACE_Export ACE_High_Res_Timer { [...] }; #if defined (__ACE_INLINE__) #include "ace/High_Res_Timer.i" #endif /* __ACE_INLINE__ */
and .cpp
file:
#define ACE_BUILD_DLL #include "ace/High_Res_Timer.h" #if !defined (__ACE_INLINE__) #include "ace/High_Res_Timer.i" #endif /* __ACE_INLINE__ */ ACE_ALLOC_HOOK_DEFINE(ACE_High_Res_Timer)
NOTE: It is very important to ensure than an
inline function will not be used before its definition is seen.
Therefore, the inline functions in the .i file should be arranged
properly. Some compilers, such as g++
with the
-Wall
option, will issue warnings for violations.
ACE_INLINE Foo::bar () { this->baz(); }
ACE_Export
must be inserted between the
class
keyword and class name for all classes that
are exported from libraries, as shown in the example above.
However, do not use
ACE_Export
for template classes!
void object_addr (const ACE_INET_Addr &); // Sets <object_addr_> cache from <host> and <port>. const ACE_INET_Addr &object_addr const (void); // Returns the <ACE_INET_Addr> for this profile.
instead of the ``set_'' and ``get_'' form.
delete
to deallocate
memory that was allocated with malloc
.
Similarly, never associate free
with
new
.
ACE_NEW
or
ACE_NEW_RETURN
should be used to
allocate memory, and delete
should
be used to deallocate it. And be careful to use the correct form,
delete
or
delete []
to correspond to the
allocation.
ACE_NEW
or
ACE_NEW_RETURN
to allocate memory,
because they check for successful allocation and set errno
appropriately if it fails.
int
.
On all currently supported ACE platforms, it is safe to cast
a pointer to or from a long
.
ACE_Time_Value (long sec, long usec = 0);So,
ACE_Time_Value (2.5)
has the unfortunate
effect of coercing the 2.5 to a long with value 2. That's
probably not what the programmer intended, and many compilers
don't warn about it.
A nice fix would be to add an ACE_Time_Value (double)
constructor. But, that would cause ambiguous overloading
due to the default value for the second argument of
ACE_Time_Value (long sec, long usec = 0)
.
We're stuck with ACE_Time_Value
, but now we
know that it's easy to avoid.
ssize_t n_bytes; // Send multicast of one byte, enough to wake up server. if ((n_bytes = multicast.send ((char *) &reply_port, sizeof reply_port)) == -1)Write it like this:
ssize_t n_bytes = multicast.send ((char *) &reply_port, sizeof reply_port) // Send multicast of one byte, enough to wake up server. if (n_bytes == -1)
But, beware if the initialization is of a static variable. A static variable is only initialized the first time its declaration is seen. Of course, we should avoid using static variables at all.
if (test) { // true branch } else { // false branch }
is preferred over:
if (! test) { // false test branch } else { // true test branch }
int (foo)
. Instead, use
one of the ACE cast macros:
return ACE_static_cast(size_t, this->count_) > that->size_;
The general usage guidelines for the four styles of casts are:
// Disallow copying by not implementing the following . . . ACE_Object_Manager (const ACE_Object_Manager &); ACE_Object_Manager &operator= (const ACE_Object_Manager &);
If the class is a template class, then the
ACE_UNIMPLEMENTED_FUNC
macro should be used:
// = Disallow copying... ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS<TYPE> &)) ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &))
ACE_UNIMPLEMENTED_FUNC
can be used with non-template
classes as well. Though for consistency and maximum safety, it
should be avoided for non-template classes.
bool
, BOOL
, or similar
types. (CORBA::Boolean is acceptable). Use int
or u_int
instead for boolean types.
-I
)
to include any directory which contains files with template
definitions. The Compaq Tru64 cxx -ptv
compiler option
may help diagnose missing template instantiation problems.
this->
member. This makes it clear to the
reader that a class member is being used. It also makes it crystal
clear to the compiler which variable/function you mean in cases
where it might make a difference.
ACE_DEBUG
for printouts,
and ACE_OS::fprintf ()
for
file I/O. Avoid using iostreams because of implementation
differences across platforms.
ACE_DEBUG
and
ACE_ERROR
don't support
%ld
of any other multicharacter format.
#include "iostream.h" class exe_foo { public: exe_foo (int data) : data_ (data) { cerr << "constructor of exception called" << endl; } ~exe_foo () { cerr << "destructor of exception called" << endl; } exe_foo (const exe_foo& foo) : data_ (foo.data_) { cerr << "copy constructor of exception called" << endl; } int data_; }; void good (int a) { throw exe_foo (a); }; void bad (int a) { exe_foo foo (a); throw foo; }; int main () { cout << endl << "First exception" << endl << endl; try { good (0); } catch (exe_foo &foo) { cerr << "exception caught: " << foo.data_ << endl; } cout << endl << "Second exception" << endl << endl; try { good (0); } catch (exe_foo foo) { cerr << "exception caught: " << foo.data_ << endl; } cout << endl << "Third exception" << endl << endl; try { bad (1); } catch (exe_foo &foo) { cerr << "exception caught: " << foo.data_ << endl; } cout << endl << "Fourth exception" << endl << endl; try { bad (1); } catch (exe_foo foo) { cerr << "exception caught: " << foo.data_ << endl; } return 0; }Output is:
First exception constructor of exception called exception caught: 0 destructor of exception called Second exception constructor of exception called copy constructor of exception called exception caught: 0 destructor of exception called destructor of exception called Third exception constructor of exception called copy constructor of exception called destructor of exception called exception caught: 1 destructor of exception called Fourth exception constructor of exception called copy constructor of exception called destructor of exception called copy constructor of exception called exception caught: 1 destructor of exception called destructor of exception called
ACE_OS
(static)
member functions instead of bare OS system calls.
ACE_OS
class are ones that have
direct equivalents on some OS platform. Functions that are
extensions should go in the ACE
class.
ACE_SYNCH_MUTEX
macro,
instead of using one of the specific mutexes, such as
ACE_Thread_Mutex
. This provides
portability between threaded and non-threaded platforms.
ACE_Singleton
,
ACE_TSS_Singleton
, or as an
ACE_Cleanup
object. See the
ACE
Singleton.h
,
Object_Manager.h
, and
Managed_Object.h
header files for more information.
Static instances of built-in types, such as
int
or any pointer type, are fine.
Construction of static instance of a user-defined type should never spawn threads. Because order of construction of statics across files is not defined by the language, it is usually assumed that only one thread exists during static construction. This allows statics suchs as locks to be safely created. We do not want to violate this assumption.
ACE_static_cast()
, ACE_dynamic_cast()
, etc.
ACE_NEW_RETURN (this->name_space_, LOCAL_NAME_SPACE, -1); if (ACE_LOG_MSG->op_status () != 0) ....This snip of code is from
ACE_Naming_Context
.
All failed constructors in ACE (should) call ACE_ERROR. This sets
the thread-specific op_status, which can be checked
by the caller. This mechanism allows the caller to check for a failed
constructor without the requiring the constructor to throw
exceptions.
open()
methods on classes that
perform initializations that can fail. This is because open()
returns an error code that's easily checked by the caller,
rather than relying on constructor and thread-specific status
values.
ACE_ASSERT
. It
must only be used to check values; it may never be used to
wrap a function call, or contain any other side effect. That's
because the statement will disappear when ACE_NDEBUG is enabled.
For example, this code is BAD:
ACE_ASSERT (this->next (retv) != 0); // BAD CODE!Instead, the above should be coded this way:
int result = this->next (retv); ACE_ASSERT (result != 0); ACE_UNUSED_ARG (result);
ACE_DEBUG
code:
ACE_DEBUG ((LM_DEBUG, "handling signal: %d iterations left\n", --this->iterations_)); // BAD CODE!Note that this won't work correctly if
ACE_NDEBUG
is
defined, for the same reason that having side-effects in
ACE_ASSERT
s won't work either, i.e., because
the code is removed.
ACE_HANDLE h = open the file (filename);
ACE_OS::unlink (filename);
This avoids leaving the temporary file even if the program crashes.
$(RM)
instead of rm
or
rm -f
in Makefiles.
THR_BOUND
thread creation
flag for time-critical threads. This ensures that the thread competes
for resources globally on Solaris. It is harmless on other platforms.
ChangeLogTag: Thu Jul 22 09:55:10 1999 David L. Levine
<[email protected]>
man perlstyle
to view it.
PATH
:eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' & eval 'exec perl -S $0 $argv:q' if 0;
.[t]cshrc
to be
processed, possibly clobbering a necessary part of
their environment.
require 5.003;
.
being
in the user's path. If the script spawns another executable
that is supposed to be in the current directory, be sure the
prefix its filename with .
.
if
statement that has just one statement must
be written with the braces:
if (condition) { statement; }This avoids bugs caused by subsequent insertion of code:
if (condition) ACE_OS::fprintf (stderr, "I need to see what's going on here\n"); statement; /* Ooops! This statement will always be executed!!!! */
Last modified .