aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/docs/html/17_intro/C++STYLE
blob: c162a1f6ad4754470ea6d4ef0a2b1a31f123e623 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366

C++ Standard Library Style Guidelines  DRAFT 2001-01-15
-------------------------------------

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.org/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. Namespaces
  namespace std
  {
    blah blah blah;
  } // namespace std

  -NOT-

  namespace std {
    blah blah blah;
  } // namespace std

12. Spacing under protected and private in class declarations:
   space above, none below
   ie

   public:
     int foo;

   -NOT-
   public:
   
     int foo;

13. Spacing WRT return statements.
   no extra spacing before returns
   ie

   }
   return __ret;

   -NOT-
   }

   return __ret;

14. Location of global variables.
   All global variables of class type, whether in the "user visable"
   space (e.g., cin) or the implementation namespace, must be defined
   as a character array with the appropriate alignment and then later
   re-initialized to the correct value.

   This is due to startup issues on certain platforms, such as AIX.
   For more explanation and examples, see src/globals.cc.  All such
   variables should be contained in that file, for simplicity.



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.
  }
} // namespace std