b2dad0e372
2000-04-21 Benjamin Kosnik <bkoz@redhat.com> * libstdc++-v3: New directory. From-SVN: r33317
311 lines
7.3 KiB
Plaintext
311 lines
7.3 KiB
Plaintext
|
|
C++ Standard Library Style Guidelines DRAFT 1999-02-26
|
|
-------------------------------------
|
|
|
|
This library is written to appropriate C++ coding standards. As such,
|
|
it is intended to precede the recommendations of the GNU Coding
|
|
Standard, which can be referenced here:
|
|
|
|
http://www.gnu.ai.mit.edu/prep/standards_toc.html
|
|
|
|
ChangeLog entries for member functions should use the
|
|
classname::member function name syntax as follows:
|
|
|
|
1999-04-15 Dennis Ritchie <dr@att.com>
|
|
|
|
* src/basic_file.cc (__basic_file::open): Fix thinko in
|
|
_G_HAVE_IO_FILE_OPEN bits.
|
|
|
|
Notable areas of divergence from what may be previous local practice
|
|
(particularly for GNU C) include:
|
|
|
|
01. Pointers and references
|
|
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.
|
|
|
|
02. Operator names and parentheses
|
|
operator==(type)
|
|
-NOT-
|
|
operator == (type) // wrong
|
|
|
|
Reason: The == is part of the function name. Separating
|
|
it makes the declaration look like an expression.
|
|
|
|
03. Function names and parentheses
|
|
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.
|
|
|
|
04. Template function indentation
|
|
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.)
|
|
|
|
05. Template class indentation
|
|
template<typename _CharT, typename _Traits>
|
|
class basic_ios : public ios_base
|
|
{
|
|
public:
|
|
// Types:
|
|
};
|
|
-NOT-
|
|
template<class _CharT, class _Traits>
|
|
class basic_ios : public ios_base
|
|
{
|
|
public:
|
|
// Types:
|
|
};
|
|
-NOT-
|
|
template<class _CharT, class _Traits>
|
|
class basic_ios : public ios_base
|
|
{
|
|
public:
|
|
// Types:
|
|
};
|
|
|
|
06. Enumerators
|
|
enum
|
|
{
|
|
space = _ISspace,
|
|
print = _ISprint,
|
|
cntrl = _IScntrl,
|
|
};
|
|
-NOT-
|
|
enum { space = _ISspace, print = _ISprint, cntrl = _IScntrl };
|
|
|
|
07. Member initialization lists
|
|
All one line, separate from class name.
|
|
|
|
gribble::gribble()
|
|
: _M_private_data(0), _M_more_stuff(0), _M_helper(0);
|
|
{ }
|
|
-NOT-
|
|
gribble::gribble() : _M_private_data(0), _M_more_stuff(0), _M_helper(0);
|
|
{ }
|
|
|
|
08. Try/Catch blocks
|
|
try {
|
|
//
|
|
}
|
|
catch(...) {
|
|
//
|
|
}
|
|
-NOT-
|
|
try { // } catch(...) { // }
|
|
|
|
09. Member functions declarations and defintions
|
|
Keywords such as extern, static, export, explicit, inline, etc
|
|
go on the line above the function name. Thus
|
|
|
|
virtual int
|
|
foo()
|
|
-NOT-
|
|
virtual int foo()
|
|
|
|
Reason: GNU coding conventions dictate return types for functions
|
|
are on a separate line than the function name and parameter list
|
|
for definitions. For C++, where we have member functions that can
|
|
. be either inline definitions or declarations, keeping to this
|
|
standard allows all member function names for a given class to be
|
|
aligned to the same margin, increasing readibility.
|
|
|
|
|
|
10. Invocation of member functions with "this->"
|
|
For non-uglified names, use this->name to call the function.
|
|
|
|
this->sync()
|
|
-NOT-
|
|
sync()
|
|
|
|
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.
|
|
|
|
--------------------------
|
|
|
|
[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>
|
|
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.
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|