Вы находитесь на странице: 1из 6

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()

reason: koenig lookup.

11. constructor member intialization lists

should look like this:


ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) :
__ctype_abstract_base<char>(__refs), _m_del(__table != 0 && __del),
_m_toupper(__ctype_toupper), _m_tolower(__ctype_tolower),
_m_ctable(static_cast<const mask*>(__ctype_b),
_m_table(__table == 0 ? _m_ctable : __table)
{ }

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

Вам также может понравиться