Friday, January 2, 2009

Working with other libraries, part 3: use consistent conventions for member types

Ever get confused by the names of member variables/types/functions of C++ class templates?

Boost.Format's basic_format class template defines five public and two private member types, using a mix of four different naming conventions!

[an extract from boost/format/format_class.hpp]

// in namespace boost
template <class Ch, class Tr, class Alloc>
class basic_format
{
private:
  typedef typename io::CompatTraits<Tr>::compatible_type compat_traits;
  typedef io::detail::stream_format_state<Ch, Tr> stream_format_state;
  
public:
  typedef Ch CharT;
  typedef std::basic_string<Ch, Tr, Alloc> string_type;
  typedef typename string_type::size_type size_type;
  typedef io::detail::format_item<Ch, Tr, Alloc> format_item_t;
  typedef io::basic_altstringbuf<Ch, Tr, Alloc> internal_streambuf_t;

In Extended STL, volume 1: Collections and Iterators I recommend the use of the following naming convention for member types:
  1. For public member types that share names with standard components that have the same logical purpose, follow the standard convention and use the standard name. An example would be iterator.
  2. For public member types that are not covered by clause 1, use the _type suffix. An example would be char_type.
  3. For private member types, use the _type_ suffix. An example would be compat_traits_type_.
and
  1. For public API (non-member) types use the _t suffix. An example would be pan_char_t.
  2. For non-public/implementation API (non-member) types use the _t_ suffix. An example would be b64ErrorString_t_.


I've been using this for many years without a blip. I can read my code, even some years later, and understand what's a type and what isn't and also, importantly, which types are for consumption in the outside world and which are internal to the component. Q.E.D.

No comments: