
C++ Standard Library Style Guidelines  DRAFT 1998-01-23
-------------------------------------

This library is written to appropriate C++ coding standards.
Notable differences from what may be previous local practice 
(particularly for GNU C) include:

  char* p = "flop";
  char& c = *p;
     -NOT-
  char *p = "flop";  // wrong
  char &c = *p;      // wrong
  
    Reason: In C++, definitions are mixed with executable code.  Here, 
            p is being initialized, not *p.  This is near-universal
            practice among C++ programmers; it is normal for C hackers
            to switch spontaneously as they gain experience.

  operator==(type)
     -NOT-
  operator == (type)  // wrong
     
    Reason: The == is part of the function name.  Separating
            it makes the declaration look like an expression. 

  template<typename T>
    void 
    template_function(args);
      -NOT-
  template<class T>
  void template_function(args);
  
     Reason: In class definitions, without indentation whitespace is
             needed both above and below the declaration to distinguish
	     it visually from other members.  (Also, re: "typename"
	     rather than "class".)  T often could be int, which is 
	     not a class.  ("class", here, is an anachronism.)

  void mangle()
     -NOT-
  void mangle ()  // wrong

     Reason: no space before parentheses (except after a control-flow
     keyword) is near-universal practice for C++.  It identifies the
     parentheses as the function-call operator or declarator, as 
     opposed to an expression or other overloaded use of parentheses.

The library currently has a mixture of GNU-C and modern C++ coding
styles.  The GNU C usages will be combed out gradually.

Name patterns:

For nonstandard names appearing in Standard headers, we are constrained 
to use names that begin with underscores.  This is called "uglification".
The convention is:

  Local and argument names:  __[a-z].*

    Examples:  __count  __ix  __s1  

  Type names and template formal-argument names: _[A-Z][^_].*

    Examples:  _Helper  _CharT  _N 

  Member data and function names: _M_.*

    Examples:  _M_num_elements  _M_initialize ()

  Static data members, constants, and enumerations: _S_.*

    Examples: _S_max_elements  _S_default_value

Don't use names in the same scope that differ only in the prefix, 
e.g. _S_top and _M_top.  See BADNAMES for a list of forbidden names.
(The most tempting of these seem to be and "_T" and "__sz".)

Names must never have "__" internally; it would confuse name unmanglers
on some targets.  Also, never use "__[0-9]", same reason.  In particular,
(IMPORTANT!) type and template names should never have a "__" prefix.

--------------------------

[BY EXAMPLE]
    
#ifndef  _HEADER_
# define _HEADER_ 1

namespace std
{
  class gribble
  {
  public:
    // ctor, op=, dtor
    gribble() throw();
    gribble (const gribble&);
    explicit gribble(int __howmany);
    gribble& operator=(const gribble&);
    virtual ~gribble() throw ();

    // argument
    inline void  public_member(const char* __arg) const;

    // in-class function definitions should be restricted to one-liners.
    int one_line() { return 0 }
    int two_lines(const char* arg) 
      { return strchr(arg, 'a'); }
    inline int three_lines();  // inline, but defined below.

    // note indentation
    template<typename _Formal_argument>
      void public_template() const throw();
    template<typename _Iterator>
      void other_template();

  private:
    class _Helper;

    int _M_private_data;
    int _M_more_stuff;
    _Helper* _M_helper;
    int _M_private_function();

    enum _Enum { _S_one, _S_two };
    static void _S_initialize_library();
  };

// More-or-less-standard language features described by lack, not presence:
# ifndef _G_NO_LONGLONG
  extern long long _G_global_with_a_good_long_name;  // avoid globals!
# endif

  // avoid in-class inline definitions, define separately;
  //   likewise for member class definitions:
  inline int
  gribble::public_member() const
    { int __local = 0; return __local; }

  class gribble::_Helper
  {
    int _M_stuff;

    friend class gribble;
  };
}

// Names beginning with "__": only for arguments and
//   local variables; never use "__" in a type name, or
//   within any name; never use "__[0-9]".

#endif /* _HEADER_ */


namespace std 
{

  template<typename T>  // notice: "typename", not "class", no space
    long_return_value_type<with_many,args>  // notice: no spaces in <...>
    function_name(char* pointer,               // "char *pointer" is wrong.
		  char* argument, 
		  const Reference& ref)
  {
    // int a_local;  /* wrong; see below. */
    if (test) { 
	nested code 
    }
    
    int a_local = 0;  // declare variable at first use.

    //  char a, b, *p;   /* wrong */
    char a = 'a';
    char b = a + 1;
    char* c = "abc";  // each variable goes on its own line, always.

    // except maybe here...
    for (unsigned i = 0, mask = 1; mask; ++i, mask <<= 1) {
	// ...
    }
  }
  
  gribble::gribble()
  : _M_private_data(0)
  , _M_more_stuff(0)
  : _M_helper(0);
  { }

  inline int 
  gribble::three_lines()
  {
    // doesn't fit in one line.
  }

}

