More C++ Idioms/Print Version
From Wikibooks, the open-content textbooks collection
Preface
| C++ has indeed become too "expert friendly" --- Bjarne Stroustrup, The Problem with Programming, Technology Review, Nov 2006.
Stroustrup's saying is true because experts are intimately familiar with the idioms in the language. With the increase in the idioms a programmer understands, the language becomes friendlier to him or her. The objective of this open content book is to present modern C++ idioms to programmers who have moderate level of familiarity with C++, and help elevate their knowledge so that C++ feels much friendlier to them. It is designed to be an exhaustive catalog of reusable idioms that expert C++ programmers often use while programming or designing using C++. This is an effort to capture their techniques and vocabulary into a single work. This book describes the idioms in a regular format: Name-Intent-Motivation-Solution-References, which is succinct and helps speed learning. By their nature, idioms tend to have appeared in the C++ community and in published work many times. An effort has been made to refer to the original source(s) where possible; if you find a reference incomplete or incorrect, please feel free to suggest or make improvements. The world is invited to catalog reusable pieces of C++ knowledge (similar to the book on design patterns by GoF). The goal here is to first build an exhaustive catalog of modern C++ idioms and later evolve it into an idiom language, just like a pattern language. Finally, the contents of this book can be redistributed under the terms of the GNU Free Documentation License. Aimed toward: Anyone with an intermediate level of knowledge in C++ and supported language paradigms |
Authors
- Sumant Tambe talk -- The initiator and lead contributor since July 2007.
- Many other C++ aficionados who continuously improve the writeup, examples, and references where necessary.
Table of Contents
- Adapter Template
- Address Of
- Algebraic Hierarchy
- Attach by Initialization
- Barton-Nackman trick
- Base-from-Member
- Boost mutant
- Calling Virtuals During Initialization
- Dynamic Binding During Initialization
- Capability Query
- Checked delete
- Clear-and-minimize
- Coercion by Member Template
- Compile Time Control Structures
- Computational Constructor
- Concrete Data Type
- Const auto_ptr
- Construct On First Use
- Construction Tracker
- Copy-and-swap
- Copy-on-write
- Counted Body (intrusive reference counting)
- Reference Counting (intrusive)
- Curiously Recurring Template Pattern
- Detached Counted Body (non-intrusive reference counting)
- Empty Base Optimization
- Emulated Exception
- enable-if
- Envelope Letter
- Erase-Remove
- Examplar
- Execute-Around Pointer
- Export Guard Macro
- Expression-template
- Fake Vtable
- Fast Pimpl
- Final Class
- Forward Declare First
- Free Function Allocators
- Friendship and the Attorney-Client
- Function Object
- Generic Container Idioms
- Cheshire Cat
- Compilation Firewall
- Handle Body
- Pimpl
- Include Guard Macro
- Inline Guard Macro
- Inner Class
- Int-To-Type
- Interface Class
- Iterator Pair
- Making New Friends
- Metafunction
- Move Constructor
- Multi-statement Macro
- Multiple Member Initialization
- Named Constructor
- Named External Argument
- Named Loop
- Named Parameter
- Named Template Parameters
- Nifty Counter
- Schwarz Counter
- Non-copyable Mixin
- Non-member get
- Non-member Non-friend Function
- Non-throwing swap
- Non-Virtual Interface
- Public Overloaded Non-Virtuals Call Protected Non-Overloaded Virtuals
- nullptr
- Object Generator
- Object Template
- Overload Set Creation
- Parameterized Base Class
- Parameterized Inheritance
- Metafunction wrapper
- Policy Clone
- Policy-based Class Design
- Polymorphic Exception
- Recursive Type Composition
- Execute-Around Object
- Resource Acquisition Is Initialization
- Scoped Locking
- Resource Return
- Runtime Static Initialization Order Idioms
- Safe bool
- Scope Guard
- SFINAE
- Substitution Failure Is Not An Error
- Shortening Long Template Names
- Shrink-to-fit
- Small Object Optimization
- Smart Pointer
- Storage Class Tracker
- Tag Dispatching
- Temporary Base Class
- The result_of technique
- Thin Template
- Trailing Parens for Method Chaining for Named parameter
- Traits
- Type Erasure
- Templated Typedef
- Type Generator
- Type Safe Enum
- Type Selection
- Virtual Constructor
- Virtual Friend Function
- More C++ Idioms/Return Type Resolver
Policy Clone
Intent
Instantiate a policy class with many different possible types without ad-hoc limitations on type of the policy classes.
Also Known As
Motivation
Highly reusable, flexible and extensible classes can be built using policy based class design techniques[1]. Sometimes, the host class of the policies need to make an exact replica of one of its policies but instantiated with different type parameter. Unfortunately, the writer of the host class template does not know the template name to instantiate beforehand. Moreover, the policy class may or may not be a template in the first place. If it is a template, then the host class may not know how many minimum type parameters are required to instantiate the parameterized policy class. If the policy class is not a template, it may not be able to participate as a policy class. This situation is quite analogous to the situation in the Factory Method (GoF) pattern where type of the object to be created is not known a priori.
template <class Apolicy> class Host { Apolicy direct_policy_use; Apolicy <SomeInternalType> InternalClone; // Problem 1: Can't do this }; template <class T, template <class T> class Apolicy> class Host2 { Apolicy <T> common_use; Apolicy <SomeInternalType> InternalClone; // Can do this now but // Problem 2: policies that require more than one type parameter can't participate. };
Solution and Sample Code
A member template struct (called rebind) is used to pass a different type parameter to the policy class template. For example,
template <typename T> class NiftyAlloc { public: template <typename Other> struct rebind // The Policy Clone idiom { typedef NiftyAlloc <Other> other; }; //... }; template <typename T, class Alloc = NiftyAlloc <T> > where HasRebind <Alloc> // Concepts: only in C++0x class Vector { public: typedef typename Alloc::template rebind<long>::other ClonePolicy; // Here, Alloc may not be a template class or a parametrized instantiation of // a class that takes unknown number of type parameters. };
Here, the Container template needs a replica of the allocation policy it is instantiated with. Therefore, it uses the rebind mechanism exposed by the NiftyAlloc policy. The type Alloc::template rebind<long>::other is same as NiftyAlloc<long>. Essentially, it says, "I don't know what kind of allocator this type is, and I don't know what it allocates, but I want an allocator just like it that allocates longs." Using C++0x concepts, the Vector class can write type concept that checks whether the Alloc policy type supports rebind concept.
To keep the compiler happy, we have to use both the keywords typename and template in the ClonePolicy typedef. The rule is as follows: If the name of a member template specialization appears after a ., ->, or :: operator, and that name has explicitly qualified template parameters, prefix the member template name with the keyword template. The Keyword typename is also necessary in the typedef because "other" is a type, not a variable.
Known Uses
- Standard Template Library
- Compilers that do not support template template parameters
Related Idioms
Meta-function wrapper idiom is a more powerful idiom than policy Clone. Policy Clone idiom indicates its purpose in a more abstract fashion than meta-function wrapper. The rebind template is essentially the meta-function wrapper.
References
- Modern C++ Design - by Andrei Alexandrescu.
- C++ Understand rebind
Coercion by Member Template
Intent
To increase flexibility of the interface of a class template by allowing the template class to participate in the same implicit type conversions (coercion) that are otherwise possible only on the type parameters of the class template.
Also Known As
Motivation
It is often useful to 'extend' the relationship between two types to their respective template class types when they are instantiated. For example, suppose that class D derives from class B. So a pointer to an object of type D can be assigned to a pointer of type B. These semantics are implicitly supported by C++ programming language. Unfortunately, types that are composed of one of these types do not share the relationship of their composed types. The rule is applicable to templates as well and therefore, Helper<D> can not be assigned to Helper<B> in general.
class B {}; class D : public B {}; template <class T> class Helper {}; B *bptr; D *dptr; bptr = dptr; // This is allowed by the language. Helper<B> hb; Helper<D> hd; hb = hd; // This is not allowed but could be very useful.
There are cases where exceptions to this rule yield more benefits and flexibility than not allowing it at all. For example, we would like to allow conversion from auto_ptr<D> to auto_ptr<B>. It is quite intuitive but not supported by the language without using coercion by member template idiom.
Solution and Sample Code
Define independent member template functions inside a class template and use the implicit type conversion supported by the parameter type in the implementation of the member template.
template <class T> class Ptr { public: Ptr () {} Ptr (Ptr const & p) : ptr (p.ptr) { std::cout << "This is copy-constructor\n"; } // Supporting coercion using member template constructor. template <class U> Ptr (Ptr <U> const & p) : ptr (p.ptr) // Implicit conversion from U to T must be allowed. { std::cout << "conversion friendly member template " "constructor is not a copy-constructor\n"; } // Member copy-assignment operator. Ptr & operator = (Ptr const & p) { ptr = p.ptr; std::cout << "member copy-assignment operator\n"; return *this; } // Supporting coercion using member template assignment operator. template <class U> Ptr & operator = (Ptr <U> const & p) { ptr = p.ptr; // Implicit conversion from U to T must be allowed. std::cout << "conversion friendly member template assignment " "operator is not a copy-assignment operator\n"; return *this; } T *ptr; }; int main (void) { Ptr <D> d_ptr; Ptr <B> b_ptr (d_ptr); // Now allowed b_ptr = d_ptr; // This is also allowed }
Even though class D is-a class B, an array of D objects is-not-an array of B objects. This is prohibited in C++ language because of slicing issues. Quite often relaxing this rule for array of pointers can yield significant flexibility. For example, an array of pointers to D should be assignable to an array of pointers to B. This idiom can achieve that. Extra care should be taken to disallow copying of array of objects of derived type to base. Partial specialization of the member template functions can be used to achieve that. Following example uses a partial specialization of U * to only allow copy of array of pointers.
template <class T> class Array { public: Array () {} Array (Array const & a) { std::copy (a.array_, a.array_ + SIZE, array_); } template <class U> Array (Array <U *> const & a) { std::copy (a.array_, a.array_ + SIZE, array_); } template <class U> Array & operator = (Array <U *> const & a) { std::copy (a.array_, a.array_ + SIZE, array_); } enum { SIZE = 10 }; T array_[SIZE]; };
Many smart pointers such as standard auto_ptr, boost shared_ptr employ this idiom.
Caveats
A typical mistake in implementation of the Coercion by Member Template idiom is an attempt to provide template copy-constructor or template assignment operator without providing their non-template versions.
A compiler will automatically generate default copy-constructor and/or copy-assignment operator if non-template versions are not provided, and it may cause hidden and non-obvious faults.
Known Uses
- std::auto_ptr
- boost::shared_ptr
Related Idioms
References
Scope Guard
Intent
- To ensure that resources are always released in face of an exception but not while returning normally
- To provide basic exception safety guarantee
Also Known As
Motivation
Resource Acquisition is Initialization (RAII) idiom allows us to acquire resources in the constructor and release them in the destructor when scope ends successfully or due to an exception. It will always release resources. This is not very flexible. Sometime we don't want to release resources if no exception is thrown but we do want to release them if exception is thrown.
Solution and Sample Code
Enhance the typical implementation of Resource Acquisition is Initialization (RAII) idiom with a conditional check.
class ScopeGuard { ScopeGuard () : engaged_ (true) { /* Acquire resources here. */ } ~ScopeGuard () { if (engaged_) { /* Release resources here. */} } void release () { engaged_ = false; /* Resources no longer be released */ } }; void some_init_function () { ScopeGuard guard; // ...... Something may throw here. If it does we release resources. guard.release (); // Resources will not be released in normal execution. }
Known Uses
- boost::mutex::scoped_lock
- boost::scoped_ptr
Related Idioms
References
Meta-function wrapper
Please see the Policy Clone idiom.
Expression Template
Intent
- To create a domain-specific embedded language (DSEL) in C++
- To support lazy evaluation of C++ expressions (e.g., mathematical expressions), which can be executed much later in the program from the point of their definition.
- To pass an expression -- not the result of the expression -- as a parameter to a function.
Also Known As
Motivation
Domain-specific languages (DSLs) is a way of developing programs where the problem to be solved is expressed using notation that is much closer to the domain of the problem rather than the usual notation (loops, conditionals, etc.) provided by procedural languages. Domain-specific embedded languages (DSELs) is a special case of DSLs where the notation is embedded in a host language (e.g., C++). Two prominent examples of DSELs based on C++ are the Boost Spirit Parser Framework and Blitz++ scientific computing library. Spirit provides a notation to write EBNF grammar directly into a C++ program whereas Blitz++ allows a notation to perform mathematical operations on matrices. Obviously, such notation is not provided in C++ natively. The key benefit of using such notation is that the program captures the intention of the programmer quite intuitively making the program much more readable. It reduces the development as well as maintenance costs dramatically.
So, how do these libraries (Spirit and Blitz++) achieve such a leap in the abstraction-level? The answer is -- you guessed it right -- Expression Templates.
The key idea behind expression templates is lazy evaluation of expressions. C++ does not support lazy evaluation of expressions natively. For example, in the code snippet below, the addition expression (x+x+x) is executed before the function foo is called.
int x; foo(x + x + x); // The addition expression does not exist beyond this line.
Function foo never really knows how the parameter it receives is computed. The addition expression never really exists after its first and the only evaluation. This default behavior of C++ is necessary and sufficient for an overwhelmingly large number of real-world programs. However, some programs need the expression later on to evaluate it again and again. For example, tripling every integer in an array.
int expression (int x) { return x + x + x; // Note the same expression. } // .... Lot of other code here const int N = 5; double A[N] = { 1, 2, 3, 4, 5}; std::transform(A, A+N, A, std::ptr_fun(expression)); // Triples every integer.
This is the conventional way of supporting lazy evaluation of mathematical expressions in C/C++. The expression is wrapped in a function and the function is passed around as a parameter. There is overhead of function calls and creation of temporaries in this technique, and quite often, the location of the expression in the source code is quite far from the call site, which adversely affects the readability and maintainability. Expression templates solve the problem by inlining the expression, which eliminates the need for a function pointer and brings together the expression and the call site.
Solution and Sample Code
Expression templates use the Recursive Type Composition idiom. Recursive type composition uses instances of class templates that contain other instances of the same template as member variables. Multiple repetitive instantiation of the same template gives rise to an abstract syntax tree (AST) of types. Recursive type composition has been used to create linear Type lists as well as binary expression trees used in the following example.
#include <iostream> #include <vector> struct Var { double operator () (double v) { return v; } }; struct Constant { double c; Constant (double d) : c (d) {} double operator () (double) { return c; } }; template < class L, class H, class OP > struct DBinaryExpression { L l_; H h_; DBinaryExpression (L l, H h) : l_ (l), h_ (h) {} double operator () (double d) { return OP::apply (l_ (d), h_(d)); } }; struct Add { static double apply (double l, double h) { return l + h; } }; template < class E > struct DExpression { E expr_; DExpression (E e) : expr_ (e) {} double operator() (double d) { return expr_(d); } }; template < class Itr, class Func > void evaluate (Itr begin, Itr end, Func func) { for (Itr i = begin; i != end; ++i) std::cout << func (*i) << std::endl; } int main (void) { typedef DExpression <Var> Variable; typedef DExpression <Constant> Literal; typedef DBinaryExpression <Variable , Literal, Add> VarLitAdder; typedef DExpression <VarLitAdder> MyAdder; Variable x ((Var())); Literal l (Constant (50.00)); VarLitAdder vl_adder(x, l); MyAdder expr (vl_adder); std::vector <double> a; a.push_back (10); a.push_back (20); evaluate (a.begin(), a.end(), expr); // It is (50.00 + x) but does not look like it. return 0; }
An analogy to the Composite design pattern is useful here. The template DExpression can be considered as the abstract base class in the Composite pattern. It captures the commonality in the interface. In expression templates, the common interface is the overloaded function call operator. DBinaryExpression is a real composite as well as an adaptor, which adapts Add's interface to that of DExpression. Constant and Var are two different types of leaf nodes. They also stick to the DExpression's interface. DExpression hides the complexity of DBinaryExpression, Constant and Var behind a unified interface to make them work together. Any binary operator can take place of Add, for example Divide, Multiply etc.
The above example does not show how recursive types are generated at compile-time. Also, expr does not look like a mathematical expression at all, but it is indeed one. The code that follows show how types are recursively composed using repetitive instantiation of the following overloaded + operator.
template< class A, class B > DExpression<DBinaryExpression<DExpression<A>, DExpression<B>, Add> > operator + (DExpression<A> a, DExpression<B> b) { typedef DBinaryExpression <DExpression<A>, DExpression<B>, Add> ExprT; return DExpression<ExprT>(ExprT(a,b)); }
The above overloaded operator+ does two things - it adds syntactic sugar and enables recursive type composition, bounded by the compiler's limits. It can therefore be used to replace the call to evaluate as follows:
evaluate (a.begin(), a.end(), x + l + x); /// It is (2*x + 50.00), which does look like a mathematical expression.
Known Uses
- Blitz++ Library
- Boost Spirit Parser Framework
- Boost Basic Linear Algebra
- LEESA: Embedding Strategic and XPath-like Object Structure Traversals in C++
Related Idioms
References
- Expression Templates - Klaus Kreft & Angelika Langer
- Expression Templates - Todd Veldhuizen
- Faster Vector Math Using Templates - Tomas Arce
Non-copyable Mixin
Intent
To prevent objects of a class from being copy-constructed or assigned to each other.
Also Known As
Motivation
Many times it makes sense to prevent copying of objects of a class. For example, class that encapsulates network connections. Copying can't be meaningfully defined for such classes. So it should be explicitly prevented without relying on guidelines or discipline on programmer's part. The intent should also be easily identifiable just by looking at the declaration of a class to improve readability.
Solution and Sample Code
A class called non-copyable is defined which has a private copy constructor and copy assignment operator.
class NonCopyable { protected: NonCopyable () {} ~NonCopyable () {} /// Protected non-virtual destructor private: NonCopyable (const NonCopyable &); NonCopyable & operator = (const NonCopyable &); }; class CantCopy : private NonCopyable {};
CantCopy objects can't be copied because the copy constructor and copy assignment operators of the private base class NonCopyable are not accessible to the derived class. The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then document why this is done. But deriving from noncopyable is simpler and clearer, and doesn't require additional documentation. private members of NonCopyable need not be defined. NonCopyable can also be categorized as a mixin-from-above because it defines a reusable module that "mixes-in" the feature of "non-copyability" into the derived class from "above". A CRTP based solution is given below.
template <class T> class NonCopyable { protected: NonCopyable () {} ~NonCopyable () {} /// Protected non-virtual destructor private: NonCopyable (const NonCopyable &); T & operator = (const T &); }; class CantCopy : private NonCopyable <CantCopy> {};
Known Uses
Related Idioms
References
Curiously Recurring Template Pattern
Intent
Specialize a base class of a derived class using the derived class as a template argument
Also Known As
- CRTP
- Mixin-from-above
Motivation
To extract out a type independent but type customizable functionality in a base class and to mix-in that interface/property/behavior into a derived class, customized for the derived class.
Solution and Sample Code
In CRTP idiom, a class T, inherits from a template that specializes on T.
class T : public X<T> {…};
This is valid only if the size of X<T> can be determined independently of T. Typically, the base class template will take advantage of the fact that member function bodies (definitions) are not instantiated until long after their declarations, and will use members of the derived class within its own member functions, via the use of a static_cast, e.g.:
template <class Derived> struct base { void interface() { // ... static_cast<Derived*>(this)->implementation(); // ... } static void static_interface() { // ... Derived::static_implementation(); // ... } // The default implementation may be (if exists) or should be (otherwise) // overriden by inheriting in derived classes (see below) void implementation(); static void static_implementation(); }; // The Curiously Recurring Template Pattern (CRTP) struct derived_1 : base<derived_1> { // This class uses base variant of implementation //void implementation(); // ... and overrides static_implementation static void static_implementation(); }; struct derived_2 : base<derived_2> { // This class overrides implementation void implementation(); // ... and uses base variant of static_implementation //static void static_implementation(); };
Known Uses
Related Idioms
References
Curiously Recurring Template Pattern on Wikipedia
Parameterized Base Class
Intent
To abstract out an aspect in a reusable module and combine it in a given type when required.
Also Known As
- Mixin-from-below
- Parameterized Inheritance
Motivation
A certain aspect can be abstracted out from requirements and be developed as templates (e.g., object serialization). Serialization is a cross-cutting concern that many classes/POD types in an application may have. Such a concern can be abstracted out in a manageable reusable module. By addition of an aspect, substitutability with the original type is not broken so another motivation is to have a IS-A (public inheritance) or WAS-A (private inheritance) relationship with the type parameter.
Solution and Sample Code
template <class T> class Serializable : public T, /// Parameterized Base Class Idiom public ISerializable { public: Serializable (const T &t = T()) : T(t) {} virtual int serialize (char *& buffer, size_t & buf_size) const { const size_t size = sizeof (T); if (size > buf_size) throw std::runtime_error("Insufficient memory!"); memcpy (buffer, static_cast<const T *>(this), size); buffer += size; buf_size -= size; return size; } };
Serializable <T> can be used polymorphically as a T as well as a ISerializable. Above example works best when T is a user-defined POD type.
Known Uses
Related Idioms
References
Parameterized Inheritance
Please see the Parameterized Base Class idiom.
Move Constructor
Intent
To transfer the ownership of a resource held by an object to a new object
Also Known As
- Colvin-Gibbons trick
Motivation
Some objects in C++ exhibit so called move semantics. For example, std::auto_ptr. In the code that follows auto_ptr b ceases to be useful after the creation of object a.
std::auto_ptr <int> b (new int (10)); std::auto_ptr <int> a (b);
The copy constructor of auto_ptr modifies its argument, and hence it does not take a const reference as a parameter. It poses no problem in the above code because object b is not a const object. But it creates a problem when a temporary is involved.
When a function returns an object by value and that returned object is used as an argument to a function (for example to construct another object of the same class), compilers create a temporary of the returned object. These temporaries are short lived and as soon as the statement is executed, the destructor of the temporary is called. The temporary therefore owns its resources for a very short time. The trouble is that temporaries are const objects by default. Therefore, they can't be used to call the constructor taking a non-const reference. A move constructor can be used in such cases.
Solution and Sample Code
template <class T> class MoveResource { private: struct proxy { T * resource_; }; T * resource_; public: MoveResource (MoveResource &m) throw () // Move constructor : resource_ (m.resource_) { m.resource_ = 0; } MoveResource (proxy p) throw () // The proxy move constructor : resource_(p.resource_) { } MoveResource & operator = (MoveResource &m) throw () { // copy and swap idiom MoveResource temp (m); temp.swap (*this); return *this; } MoveResource & operator = (proxy p) throw () { // copy and swap idiom MoveResource temp (p); temp.swap (*this); return *this; } void swap (MoveResource &m) throw () { std::swap (this->resource_, m.resource_); } operator proxy () throw () // A helper conversion function { proxy p; p.resource_ = this->resource_; this->resource_ = 0; return p; } };
It is important that these functions be non-throwing to guarantee at least basic exception guarantee. The compiler figures out the right sequence of conversion functions when a MoveResource is being constructed from a returned value of a function. It first calls the operator proxy() conversion operator and then it invokes the proxy move constructor. No exceptions should be thrown in the meanwhile, otherwise there will be resource leaks.
The upcoming feature of C++0x language standard, Rvalue references, will eliminate the need of the Move Constructor idiom.
Known Uses
std::auto_ptr
Related Idioms
References
- Move Constructors - by M. D. Wilson
- auto_ptr and auto_ptr_ref - by Nicolai Josuttis
- Change Of Authority and Thread Safe Interface goes synchronized - by Philipp Bachmann
- A Brief Introduction to Rvalue References
Safe Bool
Intent
To provide boolean tests for a class but restricting it from taking participation in unwanted expressions.
Also Known As
Motivation
User provided boolean conversion functions can cause more harm than benefit because it allows them to participate in expressions you would not ideally want them to. If a simple conversion operator is defined then two or more objects of unrelated classes can be compared. Type safety is compromised. For example,
struct Testable { operator bool() const { return false; } }; struct AnotherTestable { operator bool() const { return true; } }; int main (void) { Testable a; AnotherTestable b; if (a == b) { /* blah blah blah*/ } if (a < 0) { /* blah blah blah*/ } // The above comparisons are accidental and are not intended but the compiler happily compiles them. return 0; }
Solution and Sample Code
Safe bool idiom allows syntactical convenience of testing using an intuitive if statement but at the same time prevents unintended statements unknowingly getting compiled in. Here is the code for the safe bool idiom.
class Testable { bool ok_; typedef void (Testable::*bool_type)() const; void this_type_does_not_support_comparisons() const {} public: explicit Testable(bool b=true):ok_(b) {} operator bool_type() const { return ok_==true ? &Testable::this_type_does_not_support_comparisons : 0; } }; class AnotherTestable ... // Identical to Testable. {}; int main (void) { Testable t1; AnotherTestable t2; if (t1) {} // Works as expected if (t2 == t1) {} // Fails to compile if (t1 < 0) {} // Fails to compile return 0; }
Reusable Solution
There are two plausible solutions: Using a base class with a virtual function for the actual logic, or a base class that knows which function to call on the derived class. As virtual functions come at a cost (especially if the class you're augmenting with Boolean tests doesn't contain any other virtual functions). See both versions below:
class safe_bool_base { public: typedef void (safe_bool_base::*bool_type)() const; void this_type_does_not_support_comparisons() const {} protected: safe_bool_base() {} safe_bool_base(const safe_bool_base&) {} safe_bool_base& operator=(const safe_bool_base&) {return *this;} ~safe_bool_base() {} }; // For testability without virtual function. template <typename T=void> class safe_bool : private safe_bool_base { // private or protected inheritance is very important here as it triggers the // access control violation in main. public: operator bool_type() const { return (static_cast<const T*>(this))->boolean_test() ? &safe_bool_base::this_type_does_not_support_comparisons : 0; } protected: ~safe_bool() {} }; // For testability with a virtual function. template<> class safe_bool<void> : private safe_bool_base { // private or protected inheritance is very important here as it triggers the // access control violation in main. public: operator bool_type() const { return boolean_test() ? &safe_bool_base::this_type_does_not_support_comparisons : 0; safe_bool_base::this_type_does_not_support_comparisons(); } protected: virtual bool boolean_test() const=0; virtual ~safe_bool() {} }; template <typename T> bool operator==(const safe_bool<T>& lhs, bool b) { if (b) { if (lhs) return true; else return false; } else { if (lhs) return false; else return true; } } template <typename T> bool operator==(bool b, const safe_bool<T>& rhs) { if (b) { if (rhs) return true; else return false; } else { if (rhs) return false; else return true; } } template <typename T, typename U> void operator==(const safe_bool<T>& lhs,const safe_bool<U>& rhs) { lhs.this_type_does_not_support_comparisons(); } template <typename T,typename U> void operator!=(const safe_bool<T>& lhs,const safe_bool<U>& rhs) { lhs.this_type_does_not_support_comparisons(); }
Here's how to use safe_bool:
#include <iostream> class Testable_with_virtual : public safe_bool<> { public: virtual ~Testable_with_virtual () {} protected: virtual bool boolean_test() const { // Perform Boolean logic here return true; } }; class Testable_without_virtual : public safe_bool <Testable_without_virtual> // CRTP idiom { public: /* NOT virtual */ bool boolean_test() const { // Perform Boolean logic here return false; } }; int main (void) { Testable_with_virtual t1, t2; Testable_without_virtual p1, p2; if (t1) {} if (p1 == false) { std::cout << "p1 == false\n"; } if (p1 == p2) {} // Does not compile, as expected if (t1 != t2) {} // Does not compile, as expected return 0; }
In C++, address of protected members functions can't be taken in a derived class. Derived class could be a standard class, a class template or a specialization of a class template. Some implementations of safe bool idiom declare safe_bool_base::this_type_does_not_support_comparisons as protected, address of which can't be taken in the derived class - a requirement in reusable safe bool idiom. Unfortunately, there is a access control bug in g++ compiler that allows taking address of safe_bool_base::this_type_does_not_support_comparisons in a class template even when it is declared protected.
Solution in C++0x
The upcoming C++0x standard provides explicit conversion operators as a parallel to explicit constructors. See N2437: Explicit Conversion Operator Draft Working Paper. Explicit conversion operators solve the problem in a clean way.
Known Uses
- boost::scoped_ptr
- boost::shared_ptr
- boost::optional
Related Idioms
References
http://www.artima.com/cppsource/safebool.html
Base-from-Member
Intent
To initialize a base class from a data-member of the derived class.
Also Known As
Motivation
Sometimes it becomes necessary to initialize a base class from a data member of the current/derived class. It sounds contradictory to the rules of C++ language because base classes are always initialized before any of the data members get a chance to execute their constructors, if any. The idiom boils down to pushing the parameter data member in a private base class and putting that private base class before the dependent base class in the derivation order. The language rules dictate that base classes are always initialized in the order of declaration.
Solution and Sample Code
Following code is obtained from Boost[1] library. Following code indicates the requirement.
#include <streambuf> // for std::streambuf #include <ostream> // for std::ostream class fdoutbuf : public std::streambuf { public: explicit fdoutbuf( int fd ); //... }; class fdostream : public std::ostream { protected: fdoutbuf buf; public: explicit fdostream( int fd ) : buf( fd ), std::ostream( &buf ) // This is not allowed. // buf can't be initialized before std::ostream. {} //... };
Here is the solution using base-from-member idiom.
#include <streambuf> // for std::streambuf #include <ostream> // for std::ostream class fdoutbuf : public std::streambuf { public: explicit fdoutbuf( int fd ); //... }; struct fdostream_pbase { fdoutbuf sbuffer; explicit fdostream_pbase( int fd ) : sbuffer( fd ) {} }; class fdostream : private fdostream_pbase , public std::ostream { typedef fdostream_pbase pbase_type; typedef std::ostream base_type; public: explicit fdostream( int fd ) : pbase_type( fd ), base_type( &sbuffer ) {} //... };
Known Uses
Related Idioms
References
- ↑ Boost Utility http://www.boost.org/libs/utility/base_from_member.html
Construction Tracker
Intent
To identify the data member that throws an exception when initialization of two or more objects in the constructor's initialization list can throw the same exception type
Also Known As
Motivation
When two or more objects are initialized in a constructor's initialization list and all of them can throw the same exception (std::exception), tracking which one of them failed become a tricky issue as there can be only one try block surrounding the initialization list. Such a try block has a special name called 'constructor try block', which is nothing but a 'function-try block'.
Solution and Sample Code
Construction Tracker idiom uses a simple technique to track successful construction on objects in the initialization list. A counter is simply incremented as constructors of objects finish successfully one-by-one. It cleverly uses bracket operator to inject the counter increments in between calls to the constructors all being invisible to the user of the class.
#include <iostream> #include <stdexcept> struct B { B (char const *) { throw std::runtime_error("B Error"); } }; struct C { C (char const *) { throw std::runtime_error("C Error"); } }; class A { B b_; C c_; enum TrackerType { NONE, ONE, TWO }; public: A( TrackerType tracker = NONE) try // A constructor try block. : b_((tracker = ONE, "hello")) // Can throw std::exception , c_((tracker = TWO, "world")) // Can throw std::exception { assert(tracker == TWO); // ... constructor body ... } catch (std::exception const & e) { if (tracker == ONE) { std::cout << "B threw: " << e.what() << std::endl; } else if (tracker == TWO) { std::cout << "C threw: " << e.what() << std::endl; } throw; } }; int main (void) { try { A a; } catch (std::exception const & e) { std::cout << "Caught: " << e.what() << std::endl; } return 0; }
The double parentheses is how the bracket operator is used to place in the assignment to the tracker. This idiom critically depends upon the constructor of B and C taking at least one parameter. If class B and C does not take parameters, then an adapter class needs to be written such that it the adapter class will accept a dummy parameter and calling the default parameters of B and C. Such an adapter can be written using More C++ Idioms/Parameterized Base Class idiom using mixin-from-below technique. The adapter class can also be completely encapsulated inside class A. In the consturctor of class A, the tracker parameter has a default value and therefore it does no bother the user.
Known Uses
Related Idioms
References
Runtime Static Initialization Order Idioms
Intent
Control the order of initialization and destruction of non-local static objects across compilation units that are otherwise ordered in an implementation dependent manner.
Motivation
- Order of initialization of static objects spread across different compilation units is not well defined. Order of destruction is the reverse of initialization order but initialization order itself is implementation defined. Bring order to this chaos.
- The destructor of static objects are non-trivial and have important side-effects that have to happen
Solution and Sample Code
The following idioms are commonly used to control the order of initialization of static objects.
Construct On First Use
Intent
Ensure that an object is initialized before its first use. Specifically, ensure that non-local static object is initialized before its first use.
Also Known As
Lazy construction/evaluation
Motivation
Static objects that have non-trivial constructors must be initialized before they are used. It is possible to access an uninitialized non-local static object before its initialization if proper care is not exercised.
struct Bar { Bar () { cout << "Bar::Bar()\n"; } void f () { cout << "Bar::f()\n"; } }; struct Foo { Foo () { bar_.f (); } static Bar bar_; }; Foo f; Bar Foo::bar_; int main () {}
In the above code, Bar::f() gets called before its constructor. It should be avoided.
Solution and Sample Code
There are 2 possible solutions, which depends upon whether the destructor of the object in consideration has non-trivial destruction semantics. Wrap the otherwise static object in a function so that function initializes it before it is used.
- Construct on first use using dynamic allocation
struct Foo { Foo () { bar().f (); } Bar & bar () { static Bar *b = new Bar (); return *b; } };
If the object has a destructor with non-trivial semantics, local static object is used instead of dynamic allocation as given below.
- Construct on first use using local static
struct Foo { Foo () { bar().f (); } Bar & bar () { static Bar b; return b; } };
Known Uses
- Singleton pattern implementations often use this idiom.
- ACE_TSS<T> class template in Adaptive Communication Environment (ACE) for creating and accessing objects in thread specific storage (TSS) uses this idiom.
Related Idioms
References
Nifty Counter
Intent
Ensure a non-local static object is initialized before its first use and destroyed only after last use of the object.
Also Known As
Motivation
When static objects use other static objects, the initialization problem becomes more complex. Static object must be initialized before its use if it has non-trivial initialization. Initialization order of static objects across compilation units is not well-defined. More than one static objects, spread across multiple compilation units, might be using a single static object. For example, std::cout. std::cout can be used in the any number of other static objects. Therefore, it must be initialized before use.
Solution and Sample Code
Nifty counter idiom is an example of reference counting idiom applied to the initialization of static objects.
//Stream.hpp class StreamInitializer; class Stream { friend class StreamInitializer; public: Stream () { // Constructor must be called before use. } }; static class StreamInitializer { public: StreamInitializer (); ~StreamInitializer (); } initializer; //Note object here in the header.
//Stream.cpp static int nifty_counter = 0; // The counter is initialized at load-time i.e., before any of the static objects are initialized. StreamInitializer::StreamInitializer () { if (0 == nifty_counter++) { // Initialize Stream object's static members. } } StreamInitializer::~StreamInitializer () { if (0 == --nifty_counter) { // Clean-up. } }
The header file of Stream class has to be included before any member function can be called on the Stream object. An instance of class StreamInitializer (called initializer) is included in each compilation unit. Any use of the Stream object follows after the inclusion of header, which ensures that the constructor of the initializer object is called before the Stream object is used.
Known Uses
Standard C++ iostream library std::cout, std::cin, std::cerr, std::clog
Related Idioms
References
Schwarz Counter
Please see the Nifty Counter idiom.
Calling Virtuals During Initialization
Intent
Simulate calling of virtual functions during object initialization.
Also Known As
Dynamic Binding During Initialization idiom
Motivation
Sometimes it is desirable to invoke virtual functions of derived classes while a derived object is being initialized. Language rules explicitely prohibit this from happening because calling member functions of derived object before derived part of the object is initialized is dangerous. It is not a problem if the virtual function does not access data members of the object being constructed. But there is no general way of ensuring it.
class Base { public: Base(); ... virtual void foo(int n) const; // often pure virtual virtual double bar() const; // often pure virtual }; Base::Base() { ... foo(42) ... bar() ... // these will not use dynamic binding // goal: simulate dynamic binding in those calls } class Derived : public Base { public: ... virtual void foo(int n) const; virtual double bar() const; };
Solution and Sample Code
There are multiple ways of achieving the desired effect. Each has its own pros and cons. In general the approaches can be divided into two catagories. One using two phase initialization and other one using only single phase initialization.
Two phase initialization technique separates object construction from initializing its state. Such a separation may not be always possible. Initialization of object's state is clubbed together in a separate function, which could be a member function or a free standing function.
class Base { public: void init(); // may or may not be virtual ... virtual void foo(int n) const; // often pure virtual virtual double bar() const; // often pure virtual }; void Base::init() { ... foo(42) ... bar() ... // most of this is copied from the original Base::Base() } class Derived : public Base { public: Derived (const char *); virtual void foo(int n) const; virtual double bar() const; };
- using non-member function
template <class Derived, class Parameter> std::auto_ptr <Base> factory (Parameter p) { std::auto_ptr <Base> ptr (new Derived (p)); ptr->init (); return ptr; }
A non-template version of this approach can be found here. The factory function can be moved inside base class but it has to be static.
class Base { public: template <class D, class Parameter> static std::auto_ptr <Base> Create (Parameter p) { std::auto_ptr <Base> ptr (new D (p)); ptr->init (); return ptr; } }; int main () { std::auto_ptr <Base> b = Base::Create <Derived> ("para"); }
Constructors of class Derived should be made private to prevent users from accidently using them. Interfaces should be easy to use correctly and hard to use incorrectly - remember? The factory function should then be friend of the derived class. In case of member create function, Base class can be friend of Derived.
- Without using two phase initialization
Achieving desired effect using a helper hierarchy is described here but an extra class hierarchy has to be maintained, which is undesirable. Passing pointers to static member functions is C'ish. Curiously Recurring Template Pattern idiom can be useful in this situation.
class Base { }; template <class D> class InitTimeCaller : public Base { protected: InitTimeCaller () { D::foo (); D::bar (); } }; class Derived : public InitTimeCaller <Derived> { public: Derived () : InitTimeCaller <Derived> () { cout << "Derived::Derived()\n"; } static void foo () { cout << "Derived::foo()\n"; } static void bar () { cout << "Derived::bar()\n"; } };
Using Base-from-member idiom more complex variations of this idioim can be created.
Known Uses
Related Idioms
References
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.6
Dynamic Binding During Initialization
Please see the Calling Virtuals During Initialization idiom.
Execute-Around Pointer
Intent
Provide a smart pointer object that transparently executes actions before and after each function call on an object, given that the actions performed are the same for all functions.[1]
Also Known As
Double application of smart pointer.
Motivation
Often times it is necessary to execute a functionality before and after every member function call of a class. For example, in a multi-threaded application it is necessary to lock before modifying the data structure and unlock it afterwards. In a data structure visualization application might be interested in the size of the data structure after every insert/delete operation.
using namespace std; class Visualizer { std::vector <int> & vect; public: Visualizer (vector<int> &v) : vect(v) {} void data_changed () { std::cout << "Now size is: " << vect.size(); } }; int main () // A data visualization application. { std::vector <int> vector; Visualizer visu (vector); //... vector.push_back (10); visu.data_changed (); vector.push_back (20); visu.data_changed (); // Many more insert/remove calls here // and corresponding calls to visualizer. }
Such a repetition of function calls is error-prone and tedious. It would be ideal if calls to visualizer could be automated. Visualizer could be used for std::list <int> as well. Such funcitonality which is not a part of single class but rather cross cuts multiple classes is commonly known as aspects. This particular idiom is useful for designing and implementing simple aspects.
Solution and Sample Code
class VisualizableVector { public: class proxy { public: proxy (vector<int> *v) : vect (v) { std::cout << "Before size is: " << vect->size (); } vector<int> * operator -> () { return vect; } ~proxy () { std::cout << "After size is: " << vect->size (); } private: vector <int> * vect; }; VisualizableVector (vector<int> *v) : vect(v) {} proxy operator -> () { return proxy (vect); } private: vector <int> * vect; }; int main() { VisualizableVector vector (new vector<int>); //... vector->push_back (10); // Note use of -> operator instead of . operator vector->push_back (20); }
Overloaded -> operator of visualizableVector creates a temporary proxy object and it is returned. Constructor of proxy object logs size of the vector. The overloaded -> operator of proxy is then called and it simply forwards the call to the underlying vector object by returning a raw pointer to it. After the real call to the vector finishes, destructor of proxy logs the size again. Thus the logging for visualization is transparent and the main function becomes free from clutter. This idiom is a special case of Execute Around Proxy, which is more general and powerful.
The real power of the idiom can be derived if we combine it judiciously with templates and chain the overloaded -> operators.
template <class NextAspect, class Para> class Aspect { protected: Aspect (Para p): para_(p) {} Para para_; public: NextAspect operator -> () { return para_; } }; template <class NextAspect, class Para> struct Visualizing : Aspect <NextAspect, Para> { public: Visualizing (Para p) : Aspect <NextAspect, Para> (p) { std::cout << "Before Visualization aspect" << std::endl; } ~Visualizing () { std::cout << "After Visualization aspect" << std::endl; } }; template <class NextAspect, class Para> struct Locking : Aspect <NextAspect, Para> { public: Locking (Para p) : Aspect <NextAspect, Para> (p) { std::cout << "Before Lock aspect" << std::endl; } ~Locking () { std::cout << "After Lock aspect" << std::endl; } }; template <class NextAspect, class Para> struct Logging : Aspect <NextAspect, Para> { public: Logging (Para p) : Aspect <NextAspect, Para> (p) { std::cout << "Before Log aspect" << std::endl; } ~Logging () { std::cout << "After Log aspect" << std::endl; } }; template <class Aspect, class Para> class AspectWeaver { public: AspectWeaver (Para p) : para_(p) {} Aspect operator -> () { return Aspect (para_); } private: Para para_; }; #define AW1(T,U) AspectWeaver <T <U, U>, U > #define AW2(T,U,V) AspectWeaver <T < U <V, V> , V>, V > #define AW3(T,U,V,X) AspectWeaver <T < U <V <X, X>, X> , X>, X > int main() { AW3(Visualizing, Locking, Logging, vector <int> *) X (new vector<int>); //... X->push_back (10); // Note use of -> operator instead of . operator X->push_back (20); return 0; }
Known Uses
Related Idioms
References
- ↑ Execute Around Sequences - Kevlin Henney
Thin Template
Intent
To reduce object code duplication when a class template is instantiated for many types.
Also Known As
Motivation
Templates is a way of reusing source code, not object code. A template can be defined for a whole family of classes. Each member of that family that is instantiated requires its own object code. Whenever a class or function template is instantiated, object code is generated specifically for that type. More the number of parameterized types, more is the generated object code. Good optimizing compilers only generate object code for functions for class templates that are used in the program. Duplicate object code could still pose a problem in environments where memory is not really abundant. Reusing the same object code could also improve instruction cache performance and thereby application performance. Therefore, it is desirable to reduce duplicate object code.
Solution and Sample Code
Thin template idiom is used reduce duplicate object code. Object code level reusable code is written only once, generally in a base class, and is compiled in a separately deployable .dll or .so file. This base class is not type safe but type safe "thin template" wrapper adds the missing type safety, without causing much (or no) object code duplication.
// Not a template class VectorBase { void insert (void *); void *at (int index); }; template <class T> class Vector<T*> // Thin template : VectorBase { inline void insert (T *t) { VectorBase::insert (t); } inline T *at (int index) { return VectorBase::at (index); } };
The base class may be fat: it may contain an arbitrary amount of code. Because this class uses only inline functions, it generates no extra code. But because the casting is encapsulated in the inline function, the class is typesafe to its users. The templated class is thin
Known Uses
Symbian OS relies on this idiom a lot. For example,
template <class T> class CArrayFix : public CArrayFixBase
where CArrayFixBase does all the work
Related Idioms
References
Non-throwing swap
Intent
- To implement an exception safe and efficient swap operation.
- To provide uniform interface to it to facilitate generic programming.
Also Known As
- Exception safe swap
Motivation
A typical implementation of swap could be given as follows:
template<class T> void swap (T &a, T &b) { T temp (a); a = b; b = temp; }
This can be problematic for two reasons:
- Performance
- Swapping of two large, complex objects of the same type is inefficient due to acquisition and release of resources for the intermediate temporary object.
- Exception-safety
- This generic swap implementation may throw if resources are not available. (Such a behavior does not make sense where in fact no new resources should have been requested in the first place.) Therefore, this implementation cannot be used for the Copy-and-swap idiom.
Solution and Sample Code
Non-throwing swap idiom uses Handle Body idiom to achieve the desired effect. The abstraction under consideration is split between two implementation classes. One is handle and other one is body. The handle holds a pointer to a body object. The swap is implemented as a simple swap of pointers, which are guaranted to not throw exceptions and it is very efficient as no new resources are acquired or released.
namespace Orange { class String { char * str; public: void swap (String &s) throw () { std::swap (this->str, s.str); } }; }
Although an efficient and exception-safe swap function can be implemented (as shown above) as a member function, non-throwing swap idiom goes further than that for simplicity, consistency, and to facilitate generic programming. An explicit specialization of std::swap should be added in the std namespace as well as the namespace of the class itself.
namespace Orange { // namespace of String void swap (String & s1, String & s2) throw () { s1.swap (s2); } } namespace std { template <> void swap (Orange::String & s1, Orange::String & s2) throw () { s1.swap (s2); } }
Adding it in two places takes care of two different common usage styles of swap (1) unqualified swap (2) fully qualified swap (e.g., std::swap). When unqualified swap is used, right swap is looked up using Koenig lookup (provided one is already defined). If fully qualified swap is used, Koenig lookup is suppressed and one in the std namespace is used instead. It is a very common practice. Remaining discussion here uses fully qualified swap only. It gives a uniform look and feel because C++ programmers often use swap function in an idiomatic way by fully qualifying it with std:: as shown below.
template <class T> void zoo (T t1, T t2) { //... int i1, i2; std::swap(i1,i2); // note uniformity std::swap(t1,t2); // Ditto here }
In such a case, the right, efficient implementation of swap is chosen when zoo is instantiated with String class defined earlier. Otherwise, the default std::swap function template would be instantiated -- completely defeating the purpose of defining the member swap and namespace scope swap function. This idiom of defining explicit specialization of swap in std namepspace is particularly useful in generic programming.
Such uniformity in using non-throwing swap idiom leads to its cascading use as given in the example below.
class UserDefined { String str; public: void swap (UserDefined & u) throw () { std::swap (str, u.str); } }; namespace std { // Full specializations of the templates in std namespace can be added in std namespace. template <> void swap (UserDefined & u1, UserDefined & u2) throw () { u1.swap (u2); } } class Myclass { UserDefined u; char * name; public: void swap (Myclass & m) throw () { std::swap (u, m.u); // cascading use of the idiom due to uniformity std::swap (name, m.name); // Ditto here } } namespace std { // Full specializations of the templates in std namespace can be added in std namespace. template <> void swap (Myclass & m1, Myclass & m2) throw () { m1.swap (m2); } };
Therefore, it is a good idea to define a specialization of std::swap for the types that are amenable to an exception safe, efficient swap implementation. The C++ standard does not currently allow us to add new templates to the std namespace, but it does allow us to specialize templates (e.g. std::swap) from that namespace and add them back in it.
Caveats
Using non-throwing swap idiom for template classes (e.g., Matrix<T>) can be a subtle issue. As per the C++98 standard, only the full specialization of std::swap is allowed to be defined inside std namespace for the user-defined types. Partial specializations or function overloading is not allowed by the language. Trying to achieve the similar effect for template classes (e.g., Matrix<T>) results into overloading of std::swap in std namepspace, which is technically undefined behavior. This is not necessarily the ideal state of affairs as indicated by some people in a spectacularly long discussion thread on comp.lang.c++.moderated news group: Namespace issues with specialized swap. The solution is either to define the overloaded swap function template in the same namespace as that of the class or ignore undefined behavior hoping that nothing will happen and wait for a fix in the next language standard.
Known Uses
All boost smart pointers (e.g., boost::shared_ptr)
Related Idioms
References
- Namespace issues with specialized swap - comp.lang.c++.moderated
Copy-and-swap
Intent
To create an exception safe implementation of overloaded assignment operator.
Also Known As
Motivation
Exception safety is a very important corner stone of highly reliable C++ software that uses exceptions to indicate "exceptional" conditions. There are at least 3 types of exception safety levels: Basic, Strong, and exception neutrality. Basic exception safety should be offered always as it is usually cheap to implement. Guaranteeing strong exception safety may not be possible in all the cases. Create a temporary and swap idiom elegantly implements a strongly exception safe assignment operator.
Solution and Sample Code
Create a temporary and swap idiom acquires new resource before it forfeits its current resource. To acquire the new resource, it uses RAII idiom. If the acquisition of the new resource is successful, it exchanges the resources using the non-throwing swap idiom. Finally, the old resource is released as a side effect of using RAII in the first step.
class String { public: String & operator = (String const &s) { String temp (s); // Copy-constructor -- RAII temp.swap (*this); // Non-throwing swap return *this; }// Old resources released when destructor of temp is called. void swap (String &s) throw (); /// See non-throwing swap idiom };
Some variations of the above implementation are also possible. A check for self assignment is not strictly necessary but can give some performance improvements.
class String { public: String & operator = (String const &s) { if (this != &s) String(s).swap (*this); // Copy-constructor and non-throwing swap // Old resources are released with the destruction of the temporary above return *this; } void swap (String &s) throw (); /// See non-throwing swap idiom };
copy elision and copy-and-swap idiom
Strictly speaking, explicit creation of a temporary inside the assignment operator is not necessary. The parameter (right hand side) of the assignment operator can be passed-by-value to the function. The parameter itself serves as a temporary.
String & operator = (String s) // the pass-by-value parameter serves as a temporary { s.swap (*this); // Non-throwing swap return *this; }// Old resources released when destructor of s is called.
This is not just a matter of convenience but in fact an optimization. If the parameter (s) binds to a lvalue (another non-const object), a copy of the object is made automatically while creating the parameter (s). However, when s binds to a rvalue (temporary object, literal), the copy is typically elided, which saves a call to a copy constructor and a destructor. In the earlier version of the assignment operator where the parameter is accepted as const reference, copy elision does not happen when the reference binds to a rvalue. This results into an additional object being created and destroyed. An example follows.
String createString(); // a function that returns a String object. String s; s = createString(); // right hand side is a rvalue. Pass-by-value style assignment operator // could be more efficient than pass-by-const-reference style assignment // operator.
Not every class benefits from this style of assignment operator. Consider a String assignment operator, which releases old memory and allocates new memory only if the existing memory is insufficient to hold a copy of the right hand side String object. In such a case, it is advisable to use the pass-by-const-reference style of the assignment operator because the pass-by-value style assignment operator will always create a new String object nullifying the memory allocation optimization.
Known Uses
Related Idioms
References
Shrink-to-fit
Intent
Minimize the capacity of a container just enough to hold existing range.
Also Known As
Motivation
Standard library containers often allocate more memory than the actual number of elements in them. Such a policy results in an optimization of saving some allocations when a container grows in size. On the other hand, when size of the container reduces, there is often leftover capacity in the container. The leftover capacity of the container can be unnecessary wastage of memory resources. Shrink-to-fit idiom has been developed to reduce the extra capacity to a minimum required capacity and thereby saving memory resources.
Solution and Sample Code
Shrink-to-fit idiom is as simple as the one given below.
std::vector<int> v; //v is swapped with its temporary copy, which is capacity optimal std::vector<int>(v).swap(v);
The first half of the statement, std::vector<int>(v), creates a temporary vector of integers and it is guaranteed[1] to allocate memory just enough to hold all the elements in the parameter, v. The second half of the statement swaps the temporary vector with v using the non-throwing swap member function. swap() is very efficient, amounting to little more than swapping pointers between the vectors. After swapping, the temporary goes out of scope and deletes the memory originally held by v, whereas v retains the memory allocated by the temporary, so it has just enough to hold the original elements in v.
- ↑ ISO/IEC 14882:1998 does not appear to document this behavior of the copy constructor. Where is this behavior guaranteed?
Solution in C++0x
In C++0x some containers declare such idiom as function shrink_to_fit(), e.g. vector, deque, basic_string. shrink_to_fit() is a non-binding request to reduce capacity() to size().
Known Uses
Related Idioms
References
- Programming Languages — C++ draft standard.
Clear-and-minimize
Intent
Clear a container and minimize the capacity of the container.
Also Known As
This is sometimes called the the swap with temporary idiom.
Motivation
Standard library containers often allocate more memory than the actual number of elements in them. Such a policy results in an optimization of saving some allocations when a container grows in size. On the other hand, when size of the container reduces, there is often leftover capacity in the container. The leftover capacity of the container can be unnecessary wastage of memory resources. clear-and-minimize idiom has been developed to clear a container and reduce the extra capacity to a minimum of zero and thereby saving memory resources.
Solution and Sample Code
Clear-and-minimize idiom is as simple as the one given below.
std::vector <int> v; //... Lots of push_backs and then lots of remove on v. std::vector<int>().swap (v);
The first half of the statement, std::vector<int>() creates a temporary vector of integers and it is guaranteed to allocate zero raw memory or an implementation minimum. The second half of the statement swaps the temporary vector with v using non-throwing swap idiom, which is efficient. After swapping, the temporary created by the compiler goes out of scope and the chunk of memory originally held by v.
Solution in C++0x
In C++0x some containers declare such idiom as function shrink_to_fit(), e.g. vector, deque, basic_string. shrink_to_fit() is a non-binding request to reduce capacity() to size().
Known Uses
Related Idioms
References
- Programming Languages — C++ draft standard.
Erase-Remove
Intent
To eliminate elements from a STL container to reduce the size of it.
Also Known As
Motivation
std::remove algorithm does not eliminate elements from the container! It simply quarantines them at the end of the container. This is because std::remove algorithm works only using a pair of forward iterators (Iterator Pair idiom) and generic concept of forward iterators does not know how to eliminate data elements from an arbitrary data structure. Only container member functions can eliminate container elements as only members know the details of internal data structure. Erase-Remove idiom is used to really eliminate data elements from a container.
Solution and Sample Code
std::remove algorithm returns an iterator to the beginning of the range of "removed" elements. It does not change the end() iterator of the container nor does the size of it. Member erase function can be used to really eliminate the members from the container in the following idiomatic way.
std::vector<int> v; // fill it up somehow v.erase(std::remove(v.begin(), v.end(), 99), v.end()); // really remove all elements with value 99
The order of evaluation of v.end() and invocation of std::remove is unimportant here because std::remove algorithm does not change end() iterator in any way and therefore, order of evaluation does not matter.
Known Uses
Related Idioms
References
Effective STL, Item 32 - Scott Meyers
Smart Pointer
Intent
To relieve the burden of duplicating changes to the signature of the body class in its handle class when Handle Body idiom or Envelope Letter idiom is in use.
Also Known As
- En Masse (whole) Delegation
Motivation
When Handle/body idiom is used, it may become necessary to duplicate the interface of the body class in the handle class because handles are used by the user code. This duplication is often tedious and error prone. Smart Pointer idiom is used to relieve this burden. Smart Pointer idiom is often used along with some sort of "smartness" in the handle class such as reference counting, automatic ownership management and so on.
Solution and Sample Code
Define an overloaded arrow operator in the handle class.
class Body; class Handle // Completely pointer like semantics { public: void set (Body *b) { body_ = b; } Body * operator -> () const throw() { return body_; } Body & operator * () const throw () { return *body_; } private: mutable Body *body_; }; int main (void) { Handle h; h.set(new Body()); h->foo(); // A way of invoking Body::foo() (*h).foo(); // Another way of invoking Body::foo() }
Using the -> operator alone mitigates the problem of duplicating interface of body class in the handle class. An alternative is to overload deference (*) operator as show in the code snippet above but it is not as natural as the earlier one. If the Handle abstraction is a some sort of pointer abstraction then both the overloaded operators should be provided (e.g., std::auto_ptr, boost::shared_ptr). If the Handle abstraction is not a pointer like abstraction then * operator need not be provided. Instead, it could useful to provide const overloaded set of arrow operators because client always interacts with the hanlde class objects. For the client code, handle is the object and hence const-ness of the handle should be propagated to corresponding body whenever it's appropriate. In general, the obscure behavior of being able to modify a non-const body object from within a constant handle should be avoided. Unlike pure pointer semantics, in some cases, automatic type conversion from Handle class to Body class is also desirable.
class Body; class Handle // Less pointer like semantics { public: void set (Body *b) { body_ = b; } Body * operator -> () throw() { return body_; } Body const * operator -> () const throw() { return body_; } operator const Body & () const // type conversion { return *body_; } operator Body & () // type conversion { return *body_; } // No operator *() private: mutable Body *body_; }; int main (void) { Handle const h; h.set(new Body()); h->foo(); // compiles only if Body::foo() is a const function. }
An alternative to using member conversion functions is to use the Non-member get idiom as shown below. The overloaded non-member get() functions must be in the same namespace as the Handle class according to the Interface Principle.
namespace H { class Body; class Handle { ... }; // As per above. Body const & get (Handle const &h) { return *h.body_; } Body & get (Handle &h) { return *h.body_; } } // end namespace H. int main (void) { H::Handle const h; h.set(new Body()); get(h).foo(); // compiles only if Body::foo() is a const function. }
Known Uses
- std::auto_ptr (Completely pointer like semantics)
- boost::shared_ptr (Completely pointer like semantics)
- CORBA Var types in C++ (TAO_Seq_Var_Base_T< T > Class in TAO (The ACE ORB) - less pointer like semantics)
Related Idioms
References
Const auto_ptr
Intent
To prevent transfer of ownership of a held resource.
Also Known As
Motivation
Often it is desirable to enforce a design decision of non-transferable ownership in code and enforce it with the help of compiler. Ownership in consideration here is of any resource such as memory, database connections and so on. const auto_ptr idiom can be used if we don't want ownership of the acquired resource to be transfered outside the scope or from one object to the another.
auto_ptr without any cv-qualifier (fancy name for const and volatile) has move semantics as described in the Move Constructor idiom. It basically means that ownership of memory is unconditionally transferred from right hand side object to the left hand side object of an assignment, but it ensures that there is always a single owner of the resource. const auto_ptr can prevent the transfer.
Solution and Sample Code
Declare the auto_ptr holding memory resource as const.
const auto_ptr <X> xptr (new X()); auto_ptr <X> yptr (xptr); // Not allowed, compilation error. xptr.release(); // Not allowed, compilation error. xptr.reset( new X() ); // Not allowed, compilation error.
Compiler issues a warning here because the copy-constructor of yptr is not really a copy-constructor but in fact it is a move constructor, which takes a non-const reference to an auto_ptr, as given in Move Constructor idiom. A non-const reference can't bind with a const variable and therefore, compiler flags an error.
Consequences
- An undesirable consequence of const auto_ptr idiom is that compiler can't provide a default copy-constructor to a class that has a const auto_ptr member in it. This is because the compiler generated copy-constructor always takes a const RHS as a parameter, which can't bind with a non-const move constructor of auto_ptr. The solution is to use Virtual Constructor idiom or use boost::scoped_ptr, which explicitly prohibits copying by denying access to assignment and copy-constructor.
Known Uses
Related Idioms
References
- http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
- http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
Checked delete
Intent
Increase safety of delete expression.
Also Known As
Motivation
The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be deleted with a delete-expression. When the class has a non-trivial destructor, or a class-specific operator delete, the behavior is undefined. Some compilers issue a warning when an incomplete type is deleted, but unfortunately, not all do, and programmers sometimes ignore or disable warnings.
Solution and Sample Code
Checked delete idiom forces compiler error if the type on which delete is invoked is not fully defined. The following is the implementation of checked_delete function template in boost. It forces a compiler error by declaring an array of negative elements if type T is not defined i.e. only a forward declaration is present.
template<class T> inline void checked_delete(T * x) { typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; (void) sizeof(type_must_be_complete); delete x; } template<class T> struct checked_deleter : std::unary_function <T *, void> { void operator()(T * x) const { boost::checked_delete(x); } };
The supplied function and class templates can be used to prevent these problems, as they require a complete type, and cause a compilation error otherwise. It is similarly applicable to array delete operator as well.
NOTE: std::auto_ptr does not use anything equivalent to checked delete. Therefore, instantiating std::auto_ptr using an incomplete type may cause undefined behavior in its destructor if at the point of declaration of the std::auto_ptr the template parameter type is not fully defined.
Known Uses
Related Idioms
References
http://www.boost.org/libs/utility/checked_delete.html
Inner Class
Intent
- Implementing multiple interfaces without multiple inheritance and yet provide natural looking up-casting.
- Provide multiple implementations of the same interface in a single abstraction.
Also Known As
Motivation
Signature of a virtual function in two independent interfaces provided by two independent class libraries may collide. It is a problem especially when a single class has to implement both the colliding functions in different ways depending upon the interface you consider. For example,
class Base1 /// Provided by Moon { public: virtual int open (int) = 0; /* virtual */ ~Base1() {} // No polymorphic deletion allowed }; class Base2 /// Provided by Jupitor { public: virtual int open (int) = 0; /* virtual */ ~Base2() {} // No polymorphic deletion allowed }; class Derived : public Base1, public Base2 { public: virtual int open (int i) { // Call from which base class? return 0; } /* virtual */ ~Derived () {} };
The inner class idiom can help solve this problem.
Solution and Sample Code
Leaving the interface classes, Base1 and Base2 unchanged we can implement the Derived class as follows.
class Derived // Note no inheritance { class Base1_Impl; friend class Base1_Impl; class Base1_Impl: public Base1 // Note public inheritance { public: Base1_Impl (Derived * p) : parent_ (p) {} virtual int open (int) { return parent_->base1_open (); } private: Derived * parent_; } base1_obj; // Note member object here. class Base2_Impl; friend class Base2_Impl; class Base2_Impl: public Base2 // Note public inheritance { public: Base2_Impl (Derived * p) : parent_ (p) {} virtual int open (int) { return parent_->base2_open (); } private: Derived * parent_; } base2_obj; // Note member object here int base1_open () {} int base2_open () {} public: Derived () : base1_obj (this), base2_obj(this) {} operator Base1 & () { return base1_obj; } operator Base2 & () { return base2_obj; } }; int base1_open (Base1 & b1) { return b1.open (1); } int base2_open (Base2 & b2) { return b2.open (2); } int main (void) { Derived d; base1_open (d); // Like upcasting in inheritance. base2_open (d); // Like upcasting in inheritance. }
Note the use of conversion operators in class Derived. (Derived class is really not a derived class!) The conversion operators allow conversion of Derived to Base1 even though they don't share inheritance relationship themselves! Use of member objects base1_obj and base2_obj eliminates the concern of object lifetime. Lifetime of member objects is same as that of the Derived object.
Known Uses
Related Idioms
References
Thinking in C++ Vol 2 - Practical Programming --- by Bruce Eckel.
Iterator Pair
Intent
Specify a range of data values without worrying about the underlying data structure used by the data values.
Also Known As
Motivation
It is well understood that it is useful to create a vector<int> from another vector<int> using a copy constructor. Similarly, it is useful to create a vector<double> from a vector<int> using Coercion by Member Template idiom applied on a member template constructor. A code example is given below.
template <class T> class vector { public: vector (const vector<T> &); // copy constructor template <class U> vector (const vector<U> &); // constructor using Coercion by Member Template Idiom. };
The vector interface is still not flexible enough for some needs. For example, A vector can't create itself from a list or a set or a POD array.
template <class T> class vector { public: vector (const list<T> &); // constructor must know how list is implemented - too bad! vector (const set<T> &); // constructor must know how set is implemented - too bad! vector (const T * pod_array); // another constructor - does not know where pod_array ends - too inflexible! };
Iterator-pair is an idiom that addresses this challenge. It is based on the Iterator design pattern (obviously!) Iterator pattern intent: Provide an object which traverses some aggregate structure, abstracting away assumptions about the implementation of that structure.
Solution and Sample Code
A pair of iterators is used to designate a beginning and an end of a range of values. By virtue of the iterator design pattern whoever (in our example vector) uses iterator pair idiom can access the range without worrying about the implementation of the aggregate data structure. The only requirement is that the iterators should expose a fixed, minimal interface such as a pre-increment operator.
template <class T> class vector { T * mem; public: template <class InputIterator> vector (InputIterator begin, InputIterator end) // Iterator-pair constructor { // allocate enough memory and store in mem. for (int i = 0; begin != end; ++i) { mem[i] = *begin; ++begin; } } }; int main (void) { std::list<int> l(4); std::fill(l.begin(),l.end(), 10); // fill up list using iterator pair technique. std::set<int> s(4); std::fill(s.begin(),s.end(), 20); // fill up set using iterator pair technique. std::vector<int> v1(l.begin(), l.end()); // create vector using iterator pair technique. std::vector<int> v2(s.begin(), s.end()); // create another vector. }
Iterator-pair idiom is often combined with member templates because the exact type of the iterators is not known apriori. It could be set<T>::iterator or list<T>::iterator or a POD array. Irrespective of the type, any generic algorithm written in terms of the iterator pairs works. It is often useful to indicate the concept that iterator types are supposed to model. In the example above, the iterators are required to model at least the InputIterator concept. More information about iterator categories (tags) and their uses are described in Tag Dispatching idiom.
Sometime iterator pair idiom is unavoidable. For example, to construct a std::string from a buffer of characters with embedded null characters iterator-pair idiom is unavoidable.
char buf[] = { 'A', 'B', 0, 'C', 0, 'D'}; std::string str1 (buf); // only creates "AB" std::string str2 (buf, buf + sizeof (buf)); // Using iterator pair. Creates "AB_C_D" // buf is start of the range and buf + sizeof (buf) is the end of the range. std::cout << str1 << " length = " << str1.length() << std::endl; // AB length = 2 std::cout << str2 << " length = " << str2.length() << std::endl; // AB_C_D length = 6
Known Uses
All standard containers
Related Idioms
References
Resource Return
Intent
To convey ownership transfer (of a resource) explicitly in the return type of a factory function.
Also Known As
Motivation
Factory functions are often used to create new resources and return them to the caller. A new resource could be raw memory, dynamically allocated object, database cursors/connections, locks and so on. An important question about resources is who owns the resource and who releases it? Many times, interfaces are developed where the caller is implicitly responsible for resource release. If the caller is not aware of this fact or simply forgets to take correct steps, it gives rise to an easy-to-use-incorrectly kind of interface. Following code snippet shows an example.
struct X { void foo() {} }; X * Xfactory() // Resource ownership implicitly transferred to the caller. { return new X; // Dynamically allocated instance } int main (void) { Xfactory()->foo(); // Dynamically allocated instance of X leaks here }
Resource Return Idiom provides different alternatives to rectify the situation and results into (somewhat) hard-to-use-incorrectly interfaces.
Solution and Sample Code
The solution is the wrap the resource in a resource-management smart pointer and return the smart pointer instead of the raw pointers. Simplest form of Resource Return Idiom is shown in the code snippet below.
struct X { void foo() {} }; std::auto_ptr<X> Xfactory() // Resource ownership explicitly transferred to the caller. { return std::auto_ptr<X> (new X); // Dynamically allocated instance } int main (void) { Xfactory()->foo(); // Dynamically allocated instance of X does not leak here }
There are several issues to be considered while determining the type of resource-management smart pointer to use to return a resource. Possible options are:
- std::auto_ptr
- boost::shared_ptr
- std::unique_ptr in C++0x
- User defined Handle/Body idiom
An excellent discussion of pros and cons of choosing one over the other are discussed at length by Scott Meyer in his article The Resource Return Problem. As long as custom deletion functionality (other than plain old delete) is not required, auto_ptrs are a quick way to use the Resource Return idiom as shown above. auto_ptrs give exclusive but transferable ownership of resources which becomes very clear just by looking at the interface. For dynamically allocated pointer-returning factory functions, boost::shared_ptr is a also good choice because it offers normal copy-semantics (e.g., it can be stored in STL containers). It also allows changes to resource release policy from normal delete operation to custom deletion without disturbing clients.
When exclusive ownership is involved in case of Resource Return idiom, Move Constructor idiom is often useful to prevent unnecessary creation and destruction of temporary objects while transferring ownership of resources.
Known Uses
Related Idioms
References
nullptr
Intent
To distinguish between an integer 0 and a null pointer.
Also Known As
Motivation
For many years C++ had an embarrassment of not having a keyword to designate a null pointer. The upcoming C++ standard, C++0x, promises to eliminate the embarrassment. C++ can't use NULL macro of C because of strong type checking of C++ makes it almost useless in expressions as below.
#define NULL ((void *)0) std::string * str = NULL; // Can't automatically cast void * to std::string * void (C::*pmf) () = &C::func; if (pmf == NULL) {} // Can't automatically cast from void * to pointer to member function.
So C++ uses literal integer 0 to designate so called null pointer. It works in overwhelmingly large number of cases but sometimes can be confusing in the presence of overloaded functions. For example, the func(int) overload below takes the precedence because the type of literal 0 is int.
void func(int); void func(double *); int main() { func (static_cast <double *>(0)); // calls func(double *) as expected func (0); // calls func(int) but double * may be desired because 0 IS also a null pointer }
More confusion arises when NULL macro is used. C++ requires that macro NULL be defined as an integral constant expression having the value of 0. So unlike in C, NULL cannot be defined as (void *)0 in the C++ standard library. Furthermore, the exact form of definition is left to the particular implementation, which means that e.g. both 0 and 0L are viable options, among some others. This is a trouble as it can cause confusion in overload resolution. Worse, the way confusing overload resolution manifests itself will vary depending on the compiler and its settings used. An illustrative case is shown in this slight modification of the example above:
#include <cstddef> void func(int); void func(double *); int main() { func (static_cast <double *>(0)); // calls func(double *) as expected func (0); // calls func(int) but double * may be desired because 0 IS also a null pointer func (NULL) // calls func(int) if NULL is defined as 0 (confusion, func(double *) was intended!) - logic error at runtime, // but the call is ambiguous if NULL is defined as 0L (yet more confusion to the unwary!) - compilation error }
Solution and Sample Code
nullptr idiom solves some of the above problems in a library of null pointer. A recent draft proposal (N2431) by Herb Sutter and Bjarne Stroustrup recommends that a new keyword nullptr be added to C++. nullptr idiom is the closest match possible today using existing C++ features. The following nullptr implementation is a variant of the library based approach suggested by Scott Meyer in his book More Effective C++.
#include <typeinfo> const // It is a const object... class nullptr_t { public: template<class T> operator T*() const // convertible to any type of null non-member pointer... { return 0; } template<class C, class T> operator T C::*() const // or any type of null member pointer... { return 0; } private: void operator&() const; // Can't take address of nullptr } nullptr = {}; struct C { void func(); }; template<typename T> void g( T* t ) {} template<typename T> void h( T t ) {} void func (double *) {} void func (int) {} int main(void) { char * ch = nullptr; // ok func (nullptr); // Calls func(double *) func (0); // Calls func(int) void (C::*pmf2)() = 0; // ok void (C::*pmf)() = nullptr; // ok nullptr_t n1, n2; n1 = n2; //nullptr_t *null = &n1; // Address can't be taken. if (nullptr == ch) {} // ok if (nullptr == pmf) {} // Valid statement; but fails on g++ 4.1.1 due to bug #33990 const int n = 0; if (nullptr == n) {} // Should not compile; but only Comeau shows an error. //int p = 0; //if (nullptr == p) {} // not ok //g (nullptr); // Can't deduce T int expr = 0; char* ch3 = expr ? nullptr : nullptr; // ch1 is the null pointer value //char* ch4 = expr ? 0 : nullptr; // error, types are not compatible //int n3 = expr ? nullptr : nullptr; // error, nullptr can’t be converted to int //int n4 = expr ? 0 : nullptr; // error, types are not compatible h( 0 ); // deduces T = int h( nullptr ); // deduces T = nullptr_t h( (float*) nullptr ); // deduces T = float* sizeof( nullptr ); // ok typeid( nullptr ); // ok throw nullptr; // ok }
Unfortunately, there seems to be a bug in gcc 4.1.1 compiler that does not recognize the comparison of nullptr with point to member function (pmf). The above code compiles on VC++ 8.0 and Comeau 4.3.10.1 beta.
Consequences
There are some disadvantages of this technique and are discussed in the N2431 proposal draft. In summary, the disadvantages are
- A header must be included to use nullptr idiom. That means it is clear that language does not have a first class keyword for null pointer.
- Compilers can’t produce meaningful error messages when nullptr is implemented as a library.
Known Uses
Related Idioms
References
Generic Container Idioms
Intent
To create generic container classes (vector, list, stack) that impose minimal requirements on their value types. The requirements being only a copy-constructor and a non-throwing destructor.
Motivation
Developing generic containers in C++ can become complex if truly generic containers (like STL) are desired. Relaxing the requirements on type T is the key behind developing truly generic containers. There a few C++ idioms to actually achieve the "lowest denominator" possible with requirements on type T.
Lets take an example of a Stack.
template<class T> class Stack { int size_; T * array_; int top_; public: Stack (int size=10) : size_(size), array_ (new T [size]), // T must support default construction top_(0) { } void push (const T & value) { array_[top_++] = value; // T must support assignment operator. } T pop () { return array_[--top_]; // T must support copy-construction. No destructor is called here } ~Stack () throw() { delete [] array_; } // T must support non-throwing destructor };
Other than some array bounds problem, above implementation looks pretty obvious. But it is quite naive. It has more requirements on type T than there needs to be. The above implementation requires following operations defined on type T:
- A default constructor for T
- A copy constructor for T
- A non-throwing destructor for T
- A copy assignment operator for T
A stack ideally, should not construct more objects in it than number of push operations performed on it. Similarly, after every pop operation, an object from stack should be popped out and destroyed. Above implementation does none of that. One of the reasons is that it uses a default constructor of type T, which is totally unnecessary.
Actually, the requirements on type T can be reduced to the following using construct and destroy generic container idioms.
- A copy constructor
- A non-throwing destructor.
Solution and Sample Code
To achieve this, a generic container should be able to allocate uninitialized memory and invoke constructor(s) only once on each element while "initializing" them. This is possible using following three generic container idioms:
#include <algorithm> // construct helper using placement new: template <class T1, class T2> void construct (T1 &p, const T2 &value) { new (&p) T1(value); // T must support copy-constructor } // destroy helper to invoke destructor explicitly. template <class T> void destroy (T const &t) throw () { t.~T(); // T must support non-throwing destructor } template<class T> class Stack { int size_; T * array_; int top_; public: Stack (int size=10) : size_(size), array_ (static_cast <T *>(::operator new (sizeof (T) * size))), // T need not support default construction top_(0) { } void push (const T & value) { construct (array_[top_++], value); // T need not support assignment operator. } T top () { return array_[top_ - 1]; // T should support copy construction } void pop() { destroy (array_[--top_]); // T destroyed } ~Stack () throw() { std::for_each(array_, array_ + top_, destroy<T>); ::operator delete(array_); // Global scope operator delete. } }; class X { public: X (int) {} // No default constructor for X. private: X & operator = (const X &); // assignment operator is private }; int main (void) { Stack <X> s; // X works with Stack! return 0; }
operator new allocates uninitialized memory. It is a fancy way of calling malloc. The construct helper template function invokes placement new and in turn invokes a copy constructor on the initialized memory. The pointer p is supposed to be one of the uninitialized memory chunks allocated using operator new. If end is an iterator pointing at an element one past the last initialized element of the container, then pointers in the range end to end_of_allocation should not point to objects of type T, but to uninitialized memory. When an element is removed from the container, destructor should be invoked on them. A destroy helper function can be helpful here as shown. Similarly, to delete a range, another overloaded destroy function which takes two iterators could be useful. It essentially invokes first destroy helper on each element in the sequence.
Known Uses
All STL containers employ similar techniques. They have minimal possible requirements on the template parameter types. On the other hand, some popular C++ libraries have stricter requirements on parameterizable types than necessary.
Related Idioms
There are several other generic container idioms.
References
Designing Exception Safe Generic Containers -- Herb Sutter
Include Guard Macro
Intent
To prevent inclusion of a header file multiple times.
Also Known As
Motivation
Including the same header file in same compilation unit is a problem because it violates a basic rule of C++: One Definition Rule (ODR). A header may get included multiple times because of direct and indirect inclusion.
Solution and Sample Code
Include Guard macro idiom is an old idiom, which is also applicable in a C program. It used simple #define to prevent inclusion of a header file multiple times in a compilation unit. Following macros are put at the very beginning and at very end of a header file.
#ifndef __MYHEADER_H // beginning #define __MYHEADER_H ... #endif // __MYHEADER_H // end
Note that programmers often have their include guard macro's start with one or more underscores, followed by uppercase letters, even though such identifiers are officially reserved for the implementation of the compiler and the Standard Library, according to the C++ Standard (ISO/IEC 14882:2003).
Some compiler support
#pragma once
as an efficient alternative to include guards. It does not require to open the header file more than once, unlike traditional include guard macro in some compilers. On many modern compilers like GCC4 or MSC++2008 #pragma once will not give better compile time performance as they recognize header guards.
Known Uses
Virtually all header files in the world!
Related Idioms
References
#pragma once in Wikipedia.
Inline Guard Macro
Intent
To conveniently control inline-ness of functions using a compiler command line macro definition switch.
Also Known As
Motivation
For debugging purpose, it is often necessary to turn off inlining of functions throughout the program. But for release version, inline functions are desirable. This indicates a need of a quick way of turning inline-ness on/off as and when desired. Moreover, such functions should be defined in header files when they are inlined and otherwise should be in the source (.cpp) file. If non-inline functions are in header files, almost always it ends up creating multiple definitions of the function. On the other hand, if inline functions are not in header files then compilation units can't fine them. In both the cases linker throws errors.
Therefore, a flexible way of inlining is often desirable but C++ language does not support it without some macro magic. The Inline Guard Macro idiom achieves this.
Solution and Sample Code
The solution is to put all the inline functions in a separate file called .ipp file and decorate each function with a macro INLINE. Header file and the implementation file is create as usual and the .ipp file in selectively included in one of the two files (header or implementation) depending upon whether inlining is desired. An example of a class Test is given below.
// test.ipp file INLINE void Test::func() {} // test.hpp file #ifndef __TEST_H // Note include guards. #define __TEST_H class Test { public: void func(); }; #ifdef _INLINE_ #define INLINE inline // Define INLINE as inline (the keyword) #include "test.ipp" // It is included only when _INLINE_ is defined #endif #endif // __TEST_H //test.cpp file #include "test.hpp" // Include header file as usual. #ifndef _INLINE_ #define INLINE // INLINE is defined as empty string #include "test.ipp" // It is included only when _INLINE_ is NOT defined. #endif
The effect of using Include Guard Macro is that depending upon whether _INLINE_ is defined or not, test.ipp gets merged with either test.cpp or test.hpp. When it gets merged with test.cpp, functions are not inlined because INLINE is defined as an empty string. On the other hand when test.ipp is merged with test.hpp, INLINE is defined as inline (the keyword). Now, what remains is to define _INLINE_ macro. Generally, all modern C/C++ compilers allow defining macros at command line. For example to compile the above program on gcc using inlining, -D _INLINE_ option is used. If no such macro is defined, the functions are automatically treated as non-inline and program compiles.
Known Uses
- ACE (Adaptive Communication Environment)
- TAO (The ACE ORB)
Related Idioms
Multi-statement Macro
Intent
To write a multi-statement (multi-line) macro.
Also Known As
Motivation
Sometimes it is useful to group two or more statements into a macro and call them like a function call. Usually, an inline function should be the first preference but things such as debug macros are almost invariably macros rather than function calls. Grouping multiple statments into one macro in a naive way could lead to compilation errors, which are not obvious at first look. For example,
#define MACRO(X,Y) { statement1; statement2; }
would fail in an if statement if a semi-colon is appended at the end.
if (cond) MACRO(10,20); // Compiler error here because of the semi-colon. else statement3;
The above statement expands to
if (cond) { statement1; statement2; }; // Compiler error here because of the semi-colon. else statement3;
giving a compiler error. Therefore, people came up with a widely used idiom for multi-statement macros, which is based on a do-while loop.
Solution and Sample Code
Here is an example of the multi-statement macro idiom.
#define MACRO(arg1, arg2) do { \
/* declarations, if any */ \
statement1; \
statement2; \
/* ... */ \
} while(0) /* (no trailing ; ) */
When the caller appends a semicolon, this expansion becomes a single statement regardless of the context. Optimizing compilers usually remove any dead tests, such as while(0). This idiom is not useful when macro is used as a parameter to a function call. Moreover, this idiom allows return statement.
func(MACRO(10,20)); // Syntax error here.
Known Uses
ACE_NEW_RETURN, ACE_NEW_NORETURN macros in Adaptive Communication Environement (ACE).
#define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \
if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
} while (0)
Related Idioms
References
Making New Friends
Intent
To simplify creation of friend functions for a class template.
Motivation
Friend functions are often used to provide some auxiliary additional interfaces for a class. For example, insertion (<<), extraction (>>) operators and overloaded arithmetic operators are often friends. Declaring friend functions of a class template is a little more complicated compared to declaring a friend function for a non-template class. There are four kinds of relationships between classes and their friends when templates are involved:
- One-to-many: A non-template function may be a friend to all template class instantiations.
- Many-to-one: All instantiations of a template function may be friends to a regular non-template class.
- One-to-one: A template function instantiated with one set of template arguments may be a friend to one template class instantiated with the same set of template arguments. This is also the relationship between a regular non-template class and a regular non-template friend function.
- Many-to-many: All instantiations of a template function may be a friend to all instantiations of the template class.
The one-to-one relationship is of interest here because setting that up in C++ requires additional syntax. An example follows.
template<typename T> class Foo { T value; public: Foo(const T& t) { value = t; } friend ostream& operator<<(ostream&, const Foo<T>&); }; template<typename T> ostream& operator<<(ostream os, const Foo<T> b) { return os << b.value; }
The above example is no good for us because the inserter is not a template but it still uses a template argument (T). This is a problem since it’s not a member function. The operator<<( ) must be a template so that distinct specialization for each T can be created.
Solution here is to declare a insertion operator template outside the class before friend declaration and adorn the friend declaration with <>. It indicates that a template declared earlier should be made friend.
// Forward declarations template<class T> class Foo; template<class T> ostream& operator<<(ostream&, const Foo<T>&); template<class T> class Foo { T val; public: Foo(const T& t) { val = t; } friend ostream& operator<< <>(ostream&, const Foo<T>&); }; template<class T> ostream& operator<<(ostream& os, const Foo<T>& b) { return os << b.value; }
A disadvantage of the above solution is that it is quite verbose.
Solution and Sample Code
Dan Saks suggested another approach to overcome the verbosity of the above solution. His solution is known as "Making New Friends" idiom. The idea is to define the friend function inside the class template as shown below.
template<typename T> class Foo { T value; public: Foo(const T& t) { value = t; } friend ostream& operator<<(ostream& os, const Foo<T>& b) { return os << b.value; } };
Such a friend function is not a template but the template as a factory for "making" new friends. A new non-template function is created for each specialization of Foo.
Known Uses
Related Idioms
References
Resource Acquisition Is Initialization
Intent
- To guarantee release of resource(s) at the end of a scope
- To provide basic exception safety guarantee
Also Known As
- Execute-Around Object
- Resource Release Is Finalization
Motivation
Resources acquired in a function scope should be released before leaving the scope unless the ownership is being transferred to another scope or object. Quite often it means a pair of function calls - one to acquire a resource and another one to release it. For example, new/delete, malloc/free, acquire/release, file-open/file-close, nested_count++/nested_count--, etc. It is quite easy to forget to write the "release" part of the resource management "contract". Sometimes the resource release function is never invoked because of control flow leaves the scope because of return or an exception. It is too dangerous to trust programmers that he/she will invoke resource release operation in all possible cases in the present and in the future. Some examples are given below.
void foo () { char * ch = new char [100]; if (...) if (...) return; else if (...) if (...) else throw "ERROR"; delete [] ch; // This may not be invoked... memory leak! } void bar () { lock.acquire(); if (...) if (...) return; else throw "ERROR"; lock.release(); // This may not be invoked... deadlock! }
This is in general control flow abstraction problem. Resource Acquisition is Initialization (RAII) is an extremely popular idiom in C++ that releaves the burden of calling "resource release" operation in a clever way.
Solution and Sample Code
The idea is to wrap the resource release operation in a destructor of an object in the scope. Language guarantees that the destructor will always be invoked (of a successfully constructed object) when control flow leaves the scope because of a return statement or an exception.
// Private copy constructor and copy assignment ensure classes derived // from class NonCopyable cannot be copied. class NonCopyable { NonCopyable (NonCopyable const &); // private copy constructor NonCopyable & operator = (NonCopyable const &); // private assignment operator }; template <class T> class AutoDelete : NonCopyable { public: AutoDelete (T * p = 0) : ptr_(p) {} ~AutoDelete () throw() { delete ptr_; } private: T *ptr_; }; class ScopedLock : NonCopyable// Scoped Lock idiom { public: ScopedLock (Lock & l) : lock_(l) { lock_.acquire(); } ~ScopedLock () throw () { lock_.release(); } private: Lock& lock_; }; void foo () { X * p = new X; AutoDelete safe_del(p); // Memory will not leak if (...) if (...) return; // No need to call delete here. // Destructor of safe_del will delete memory } void X::bar() { ScopedLock safe_lock(l); // Lock will be released certainly if (...) if (...) throw "ERROR"; // No need to call release here. // Destructor of safe_lock will release the lock }
Acquiring resource(s) in constructor is not mandatory in RAII idiom but releasing resources in the destructor is the key. Therefore, it is also known (rarely though) as Resource Release is Finalization idiom. It is important in this idiom that the destructor should not throw exceptions. Therefore, the destructors have no-throw specification but it is optional. std::auto_ptr and boost::scoped_ptr are ways of quickly using RAII idiom for memory resources. RAII is also used to ensure exception safety. RAII makes it possible to avoid resource leaks without extensive use of try/catch blocks and is widely used in the software industry.
Many classes that manage resources using RAII, do not have legitimate copy semantics (e.g., network connections, database cursors, mutex). The NonCopyable class shown before prevents copying of objects that implement RAII. It simply prevents access to the copy-constructor and the copy-assignment operator by making them private. boost::scoped_ptr is an example of one such class that prevents copying while holding memory resources. The NonCopyable class states this intention explicitly and prevents compilation if used incorrectly. Such classes should not be used in STL containers. However, every resource management class that implements RAII does not have to be non-copyable like the above two examples. If copy semantics are desired, boost::shared_ptr can be used to manage memory resources. In general, non-intrusive reference counting is used to provide copy semantics as well as RAII.
Consequences
RAII is not without its limitations. The resources which are not memory and must be released deterministically and may throw exceptions usually aren't handled very well by C++ destructors. That's because a C++ destructor can't propagate errors to the enclosing scope (which is potentially winding up). It has no return value and it should not propagate exceptions outside itself. If exceptions are possible, then the destructor must handle the exceptional case within itself somehow. Nevertheless, RAII remains the most widely used resource management idiom in C++.
Known Uses
- Virtually all non-trivial C++ software
- std::auto_ptr
- boost::scoped_ptr
- boost::mutex::scoped_lock
Related Idioms
- Scope Guard
- Reference Counting
- Non copyable
- Scoped Locking idiom is a special case of RAII applied to operating system synchronization primitives such as mutex and semaphores.
References
- Resource Acquisition Is Initialization on Wikipedia
- Exception Safety: Concepts and Techniques -- Bjarne Stroustrup
- The RAII Programming Idiom
- Sutter, Herb (1999). Exceptional C++. Addison-Wesley. ISBN 0-201-61562-2.
- C++ Patterns: Execute Around Sequences - Kevlin Henney
Execute-Around Object
Please see the Resource Acquisition Is Initialization idiom.
Scoped Locking
Please see the Resource Acquisition Is Initialization idiom.
Interface Class
Intent
- To separate an interface of a class from its implementation.
- Invoke implementation of an abstraction/class using runtime polymorphism.
Also Known As
Motivation
Separating an interface of a class from its implementation is fundamental to good quality object oriented software design/programming. For object oriented programming, the principle mechanism of separation is the Interface Class. However C++ (when compared to, say, Java) provides no exclusive mechanism for expressing such a separation. In Java, interface keyword is used to specify only the public methods that are supported by an abstraction. C++ does not have such a keyword but its functionality can be expressed closely using the Interface Class idiom. The idea is to express only the public methods of an abstraction and provide no implementation of any of them. Also, lack of implementation means no instances of the interface class should be allowed.
Solution and Sample Code
An interface class contains only a virtual destructor and pure virtual functions, thus providing a construct similar to the interface constructs of other languages (e.g. Java). An interface class is a class that specifies the polymorphic interface i.e. pure virtual function declarations into a base class. The programmer using a class hierarchy can then do so via a base class that communicates only the interface of classes in the hierarchy.
class shape // An interface class { public: virtual ~shape(); virtual void move_x(int x) = 0; virtual void move_y(int y) = 0; virtual void draw() = 0; //... }; class line : public shape { public: virtual ~line(); virtual void move_x(int x); // implements move_x virtual void move_y(int y); // implements move_y virtual void draw(); // implements draw private: point end_point_1, end_point_2; //... }; int main (void) { std::vector<shape *> shapes; // Fill up shapes vector somehow. for (vector<shape *>::iterator iter (shapes.begin()); iter != shapes.end(); ++iter) { iter->draw(); } // Clean up shapes vector. (Normally we would use something like boost::shared_ptr to automate cleanup, // this is for illustration only) }
Every interface class should have a virtual destructor. Virtual destructor makes sure that when a shape is deleted polymorphically, correct destructor of the derived class is invoked. Otherwise there is a good chance of resource leak. Benefit of expressing design using interface classes are many:
- New shape abstractions can be added without changing the code that depends only on shape interface. For example, Square can inherit from shape and implement the interface methods in its own way. The function main() needs no changes at all.
- Separation of interface from implementation prevents recompilation of parts of the program that depend only on the interface classes.
- Dependency Inversion Principle (DIP) states that implementation classes should not depend on each other. Instead, they should depend on common abstraction represented using an interface class. DIP reduces coupling in a object-oriented system.
Known Uses
Nearly all good object-oriented software in C++!
Related Idioms
References
C++ Interface Classes - An Introduction
Capability Query
Intent
To check at runtime whether an object supports an interface
Also Known As
Motivation
Separating interface from implementation is a good object oriented software design practice. In C++, Interface Class idiom is used to separate interface from implementation and invoke the public methods of any abstraction using runtime polymorphism. Extending the example in the interface class idiom, a concrete class may implement multiple interfaces as shown below.
class Shape { // An interface class public: virtual ~Shape(); virtual void draw() const = 0; //... }; class Rollable { // One more interface class public: virtual ~Rollable(); virtual void roll() = 0; }; class Circle : public Shape, public Rollable { // circles roll - concrete class //... void draw() const; void roll(); //... }; class Square : public Shape { // squares don't roll - concrete class //... void draw() const; //... };
Now if we are given a container of pointers to abstract Rollable class, we can simply invoke roll function on every pointer as described in the interface class idiom.
std::vector<Rollable *> rollables; // Fill up rollables vector somehow. for (vector<Rollable *>::iterator iter (rollables.begin()); iter != rollables.end(); ++iter) { iter->roll(); }
Sometime it is not possible to know in advance whether an object implements a particular interface. Such situation commonly arises if an object inherits from multiple interface classes. To precisely find out at runtime whether an object implements an interface or not capability query is used.
Solution and Sample Code
In C++, a capability query is typically expressed as a dynamic_cast between unrelated types .
Shape *s = getSomeShape(); if (Rollable *roller = dynamic_cast<Rollable *>(s)) roller->roll();
This use of dynamic_cast is often called a cross-cast, because it attempts a conversion across a hierarchy, rather than up or down a hierarchy. In our example hierarchy of shapes and rollables, dynamic_cast to Rollable will succeed only for Circle and not for Square as the later one does not inherit from Rollable interface class.
Excessive use of capability queries is often an indication of bad object-oriented design.
Known Uses
Acyclic Visitor Pattern - Robert C. Martin.
Related Idioms
References
Capability Queries - C++ Common Knowledge by Stephen C. Dewhurst
Handle Body
Intent
- Separating Interface from Implementation
- Insulate (prevent recompilation of) the clients of a class from the changes in its implementation detail.
Also Known As
Motivation
In C++, a class is used for declaring interface as well as defining implementation. The private member functions, although not part of the "interface" of the class, must be declared in the class and are visible to the clients. Changes to the declaration of private data members, or signature of private functions require clients to recompile code. It is therefore useful to separate interface of a class from its implementation and prevent unnecessary recompilations.
Solution and Sample Code
Split an abstraction into two implementation classes. One takes on the role of an identifier and presents the class interface to the user. It is called the handle. The other class embodies the implementation and is called the body. The handle forwards member function invocations to the body.
// file String.hpp class StringRep; // Forward declaration only. class String { public: String(); String(const String &s); String &operator=(const String &s); ~String(); String(const char *s); . . . . private: StringRep *rep; // Pointer to implementation (pimpl) }; // file String.hpp ends here // file String.cpp #include "String.hpp" namespace { // Anonymous namespace class StringRep { // This should be in a separate source file than class String, so it can be compiled // separately, and made invisible to the client friend class String; StringRep(const char *s); ~StringRep(); int count; char *rep; }; } // anonymous namespace ends String::String() // constructors and everything else
Data changes can now safely be made to the implementation (body) without recompiling clients of the handle. The implementation becomes "more hidden" behind a pointer, hence the name: Compilation Firewall.
Consequences
- The extra level of indirection has a performance cost.
- This idiom doesn't address the issues of deep versus shallow copy and other runtime dynamics; See Counted Body, Envelope Letter.
- The idiom also makes inheritance less useful. See Handle Body Hierarchy to overcome this shortcoming.
- This idiom has limits in managing the dynamically allocated memory of the body class; see Counted Body.
- It also introduces the need for occasional redundant update to the handle and body classes, a problem addressed in part by Envelope Letter and Smart Pointer.
Known Uses
- Vast majority of non-trivial C++ software!
Related Idioms
References
- http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#HandleBody
- Making Pimpl Easy -- Vladimir Batov
Copyright
Original copyright ©1998 Lucent Technologies, Bell Labs Innovations. All rights reserved. Permission granted to reprint verbatim for non-commercial use provided this copyright notice appears. (Contents edited for Wikibooks).
Cheshire Cat
Please see the Handle Body idiom.
Compilation Firewall
Please see the Handle Body idiom.
Counted Body/Reference Counting (intrusive)
Intent
Manage logical sharing of a resource/object, prevent expensive copying, and allow proper resource deallocation of objects that use dynamically allocated resources.
Also Known As
- Reference Counting (intrusive)
- Counted Body
Motivation
When Handle/Body idiom is used, quite often it is noticed that copying of bodies is expensive. This is because copying of bodies involves allocation of memory and copy construction. Copying can be avoided by using pointers and references, but these leave the problem of who is responsible for cleaning up the object. Some handle must be responsible for releasing memory resources allocated for the body. Usually it is the last one. Without automatic reclamation of memory resources of memory, it leaves a user-visible distinction between built-in types and user-defined types.
Solution and Sample Code
The solution is to add a reference count to the body class to facilitate memory management; hence the name "Counted Body." Memory management is added to the handle class, particularly to its implementation of initialization, assignment, copying, and destruction.
namespace { // anonymous namespace class StringRep { friend class String; StringRep(const char *s): count(1) { strcpy(rep=new char[strlen(s)+1], s); } ~StringRep() { delete [] rep; } int count; char *rep; }; } // anonymous namespace class String { public: String():rep(new StringRep("")) { } String(const String &s): rep(s.rep) { rep->count++; } String &operator=(const String &s){ String(s).swap(*this); // copy-and-swap idiom return *this; } ~String() { // StringRep deleted only when the last handle goes out of scope. if(rep && --rep->count <= 0) delete rep; } String(const char *s): rep(new StringRep(s)) { } void swap (String & s) throw () { std::swap(this->rep, s.rep); } . . . . private: StringRep *rep; }; int main() { String a = "hello", b = "world"; a = b; return 0; }
Gratuitous copying is avoided, leading to a more efficient implementation. This idiom presumes that the programmer can edit the source code for the body. When that's not possible, use Detached Counted Body. When counter is stored inside body class, it is called intrusive reference counting and when the counter is stored external to the body class it is known as non-intrusive reference counting. This implementation is a variation of shallow copy with the semantics of deep copy and the efficiency of Smalltalk name-value pairs.
Consequences
Creation of multiple reference counts will result into multiple deletion of the same body, which is undefined. Care must be taken to avoid creating multiple reference counts to the same body. Intrusive reference counting easily supports it. With non-intrusive reference counting, programmer discipline is required to prevent duplicate reference counts.
Known Uses
- boost::shared_ptr (non-intrusive reference counting)
- boost::intrusive_ptr (intrusive reference counting)
- std::tr1::shared_ptr
- the Qt toolkit, e.g. QString
Related Idioms
- Handle Body
- Detached Counted Body (non-intrusive reference counting)
- Smart Pointer
- Copy-and-swap
References
http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#CountedBody
Copyright
Copyright ©1998 Lucent Technologies, Bell Labs Innovations. All rights reserved. Permission granted to reprint verbatim for non-commercial use provided this copyright notice appears. (Contents modified and enhanced for Wikibooks)
Detached Counted Body/Reference Counting (non-intrusive)
Intent
Adding reference counting to an object to which a reference count cannot directly be added.
Also Known As
- Reference Counting (non-intrusive)
- Detached Counted Body
Motivation
Some times Counted Body idiom can't be applied to certain classes when their sources are not available. We might only have object code and a header file. Detached Counted Body or non-intrusive reference counting can be used in such cases to prevent expensive copies of bodies.
Solution and Sample Code
Associate both a shared count, and a separate shared body, with each instance of a common handle abstraction:
class String { public: String(): rep(new char[1]), count(new int(1)) { rep[0] = '\0'; } String(const String &s): rep(s.rep), count(s.count) { (*count)++; } String &operator=(const String &s) { String temp(s); this->swap(temp); return *this; } void swap (String & s) throw () { std::swap (this->count, s.count); std::swap (this->rep, s.rep); } ~String() { if(--*count <= 0) { delete [] rep; delete count; } } String(const char *s): count(new int(1)), rep(new char[strlen(s)+1]) { strcpy(rep,s); } . . . . private: char *rep; int *count; }; int main() { String a = "hello", b = "world"; a = b; return 0; }
Consequences
Handles are slightly more expensive to copy than in Counted Body, memory fragmentation may increase, and initial construction overhead is higher because we are allocating multiple blocks.
Known Uses
- boost::shared_ptr
- ACE_Refcounted_Auto_Ptr
Related Idioms
References
http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#DetachedCountedBody
Copyright
Copyright ©1998 Lucent Technologies, Bell Labs Innovations. All rights reserved. Permission granted to reprint verbatim for non-commercial use provided this copyright notice appears. (Contents modified and enhanced for Wikibooks)
Envelope Letter
Intent
Supporting multiple implementations of a single abstract data type (ADT) instance across its lifetime
Motivation
When using Handle Body idiom and/or Counted Body idiom, quite often we come across situations where not only multiple implementations of an ADT share a common signature but also all the implementations (bodies) of a given ADT share signature with the ADT's interface (handle). In such cases, adding a new operation to a handle/body pair causes redundant update to both classes. If we want to capture this relationship between handle and body interfaces, envelope/letter idiom is used.
Solution and Sample Code
Derive all body classes from a common base class. To reflect the commonality in signature between the handle and the body, use the handle class as the common base class for alternative bodies. Make handle member functions virtual. Each alternative implementation derived from the handle class (in its role as the class defining the interface to the implementations) overrides suitable virtual functions. The base class implementation of these member functions defines the handle class functionality: it forwards requests to its associated body class instance.
class RealNumber; class ComplexNumber; class Number { public: virtual Number multiply (Number const &); protected: Number * nptr; }; class ComplexNumber : public Number { public: virtual Number multiply (Number const & n) { // ... if (this becomes a RealNumber number after multiplication) { this->nptr = new RealNumber (...); // metamorphize // .... } // .... } }; class RealNumber : public Number { // ... };
The ADT instance can now "metamorphize" between different body classes at run time. For example, A ComplexNumber can change itself to a Realnumber if its imaginary part becomes zero after some mathematical operation. An advantage of such a dynamic change in type is often increased efficiency. Moreover, new signatures need be added in one less place than if the information were duplicated. This idiom is the basis for Virtual Constructor idiom. In Algebraic Hierarchy, this pattern forms the basis for a Promotion Ladder.
Known Uses
Related Idioms
References
- http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#EnvelopeLetter
- Advanced C++ Programming Styles and Idioms by James Coplien, Addison Wesley, 1992.
Copyright
Copyright ©1998 Lucent Technologies, Bell Labs Innovations. All rights reserved. Permission granted to reprint verbatim for non-commercial use provided this copyright notice appears.
Algebraic Hierarchy
Intent
To hide multiple closely related algebraic abstractions (numbers) behind a single generic abstraction and provide a generic interface to it.
Also Known As
- State (Gamma et al.)
Motivation
In pure object-oriented languages like Smalltalk, variables are run-time bindings to objects that act like labels. Binding a variable to an object is like sticking a label on it. Assignment in these languages is analogous to peeling a label off one object and putting it on another. On the other hand, in C and C++, variables are synonyms for addresses or offsets instead of being labels for objects. Assignment does not mean re-labelling, it means overwriting old contents with new one. Algebraic Hierarchy idiom uses delegated polymorphism to simulate weak variable to object binding in C++. Algebraic Hierarchy uses Envelope Letter idiom in its implementation. The motivation behind this idiom is to be able write code like the one below.
Number n1 = Complex (1, 2); // Label n1 for a complex number Number n2 = Real (10); // Label n2 for a real number Number n3 = n1 + n2; // Result of addition is labelled n3 Number n2 = n3; // Re-labelling
Solution and Sample Code
Complete code showing implementation of Algebraic Hierarchy idiom is show below.
#include <iostream> using namespace std; struct BaseConstructor { BaseConstructor(int=0) {} }; class RealNumber; class Complex; class Number; class Number { friend class RealNumber; friend class Complex; public: Number (); Number & operator = (const Number &n); Number (const Number &n); virtual ~Number(); virtual Number operator + (Number const &n) const; void swap (Number &n) throw (); static Number makeReal (double r); static Number makeComplex (double rpart, double ipart); protected: Number (BaseConstructor); private: void redefine (Number *n); virtual Number complexAdd (Number const &n) const; virtual Number realAdd (Number const &n) const; Number *rep; short referenceCount; }; class Complex : public Number { friend class RealNumber; friend class Number; Complex (double d, double e); Complex (const Complex &c); virtual ~Complex (); virtual Number operator + (Number const &n) const; virtual Number realAdd (Number const &n) const; virtual Number complexAdd (Number const &n) const; double rpart, ipart; }; class RealNumber : public Number { friend class Complex; friend class Number; RealNumber (double r); RealNumber (const RealNumber &r); virtual ~RealNumber (); virtual Number operator + (Number const &n) const; virtual Number realAdd (Number const &n) const; virtual Number complexAdd (Number const &n) const; double val; }; /// Used only by the letters. Number::Number (BaseConstructor) : rep (0), referenceCount (1) {} /// Used by user and static factory functions. Number::Number () : rep (0), referenceCount (0) {} /// Used by user and static factory functions. Number::Number (const Number &n) : rep (n.rep), referenceCount (0) { cout << "Constructing a Number using Number::Number\n"; if (n.rep) n.rep->referenceCount++; } Number Number::makeReal (double r) { Number n; n.redefine (new RealNumber (r)); return n; } Number Number::makeComplex (double rpart, double ipart) { Number n; n.redefine (new Complex (rpart, ipart)); return n; } Number::~Number() { if (rep && --rep->referenceCount == 0) delete rep; } Number & Number::operator = (const Number &n) { cout << "Assigning a Number using Number::operator=\n"; Number temp (n); this->swap (temp); return *this; } void Number::swap (Number &n) throw () { std::swap (this->rep, n.rep); } Number Number::operator + (Number const &n) const { return rep->operator + (n); } Number Number::complexAdd (Number const &n) const { return rep->complexAdd (n); } Number Number::realAdd (Number const &n) const { return rep->realAdd (n); } void Number::redefine (Number *n) { if (rep && --rep->referenceCount == 0) delete rep; rep = n; } Complex::Complex (double d, double e) : Number (BaseConstructor()), rpart (d), ipart (e) { cout << "Constructing a Complex\n"; } Complex::Complex (const Complex &c) : Number (BaseConstructor()), rpart (c.rpart), ipart (c.ipart) { cout << "Constructing a Complex using Complex::Complex\n"; } Complex::~Complex() { cout << "Inside Complex::~Complex()\n"; } Number Complex::operator + (Number const &n) const { return n.complexAdd (*this); } Number Complex::realAdd (Number const &n) const { cout << "Complex::realAdd\n"; RealNumber const *rn = dynamic_cast <RealNumber const *> (&n); return Number::makeComplex (this->rpart + rn->val, this->ipart); } Number Complex::complexAdd (Number const &n) const { cout << "Complex::complexAdd\n"; Complex const *cn = dynamic_cast <Complex const *> (&n); return Number::makeComplex (this->rpart + cn->rpart, this->ipart + cn->ipart); } RealNumber::RealNumber (double r) : Number (BaseConstructor()), val (r) { cout << "Constructing a RealNumber\n"; } RealNumber::RealNumber (const RealNumber &r) : Number (BaseConstructor()), val (r.val) { cout << "Constructing a RealNumber using RealNumber::RealNumber\n"; } RealNumber::~RealNumber() { cout << "Inside RealNumber::~RealNumber()\n"; } Number RealNumber::operator + (Number const &n) const { return n.realAdd (*this); } Number RealNumber::realAdd (Number const &n) const { cout << "RealNumber::realAdd\n"; RealNumber const *rn = dynamic_cast <RealNumber const *> (&n); return Number::makeReal (this->val + rn->val); } Number RealNumber::complexAdd (Number const &n) const { cout << "RealNumber::complexAdd\n"; Complex const *cn = dynamic_cast <Complex const *> (&n); return Number::makeComplex (this->val + cn->rpart, cn->ipart); } namespace std { template <> void swap (Number & n1, Number & n2) { n1.swap (n2); } } int main (void) { Number n1 = Number::makeComplex (1, 2); Number n2 = Number::makeReal (10); Number n3 = n1 + n2; cout << "Finished\n"; return 0; }
Known Uses
Related Idioms
References
Advanced C++ Programming Styles and Idioms by James Coplien, Addison Wesley, 1992.
Virtual Constructor
Intent
To create a copy of an object or a new object without knowing its concrete type.
Also Known As
Factory Method of initialization
Motivation
Uses of calling member functions in a class hierarchy polymorphically are well known in the object-oriented programming community. It is a way of implementing the is-a (or more practically, behaves-as-a) relationship. Sometimes it is useful to call life-cycle management (creation, copy, and destruction) functions of a class hierarchy polymorphically.
C++ natively supports polymorphic destruction of objects using a virtual destructor. An equivalent support for creation and coping of objects is missing. In C++, creation of object(s) always requires its type to be known at compile-time. The Virtual Constructor idiom allows polymorphic creation of and coping of objects in C++.
Solution and Sample Code
The effect of a virtual constructor by a create() member function for creation and a clone() member function for copy construction as shown below.
class Employee { public: virtual ~Employee () {} // Native support for polymorphic destruction. virtual Employee * create () const = 0; // Virtual constructor (creation) virtual Employee * clone () const = 0; // Virtual constructor (copying) }; class Manager : public Employee // "is-a" relationship { public: Manager (); // Default constructor Manager (Manager const &); // Copy constructor ~Manager () {} // Destructor Manager * create () const // Virtual constructor (creation) { return new Manager(); } Manager * clone () const // Virtual constructor (copying) { return new Manager (*this); } }; class Programmer : public Employee { /* Very similar to the Manager class */ }; Employee * duplicate (Employee const & e) { return e.clone(); // Using virtual constructor idiom. }
The Manager class implements the two pure virtual functions and uses the type name (Manager) to create them. The function duplicate shows how virtual constructor idiom is used. It does not really know what it is duplicating. It only knows that it is cloning an Employee. The responsibility of creating the right instance is deligated to the derived classes. The duplicate function is therefore closed for modifications even though the class hierarchy rooted at Employee gets more sub-classes added in the future.
The return type of the clone and create member functions of the Manager class is not Employee but the class itself. C++ allows this flexibility in types where the return type of the over-ridden function can be a derived type of that of the function in the base class. This language feature is known as co-variant return types.
To handle resource ownership properly, the Resource Return idiom should be employed for the return types of clone() and create() functions as they are factory functions. If used, the return types (shared_ptr<Employee> and shared_ptr<Manager>) are no longer covariant return types and program should fail to compile. In such a case, the virtual constructor functions in the derived class should return the exact type as in the parent class.
#include <tr1/memory> class Employee { public: typedef std::tr1::shared_ptr<Employee> Ptr; virtual ~Employee () {} // Native support for polymorphic destruction. virtual Ptr create () const = 0; // Virtual constructor (creation) virtual Ptr clone () const = 0; // Virtual constructor (copying) }; class Manager : public Employee // "is-a" relationship { public: Manager () {} // Default constructor Manager (Manager const &) {} // Copy constructor ~Manager () {} Ptr create () const // Virtual constructor (creation) { return Ptr(new Manager()); } Ptr clone () const // Virtual constructor (copying) { return Ptr(new Manager (*this)); } };
Known Uses
Related Idioms
References
Concrete Data Type
Intent
To control object's scope and lifetime by allowing or disallowing dynamic allocation using the free store (heap)
Also Known As
Motivation
C++ provides two ways of controlling lifetime of an object and binding it with a program level identifier (variable). First is a scoped variable and an object, which are destroyed immediately after the scope ends (e.g., function scope integers). Second is a scoped variable (often a pointer) and a dynamically allocated object in the free store. In this case, at the end of the scope of the variable, the variable ceases to exist but the object's lifetime continues (e.g., singletons, a window object). It is possible to force the choice of the lifetime of an object either first way or the second using the Concrete Data Type idiom.
Solution and Sample Code
This idiom simply uses class level access modifiers (private, protected) to achieve the goal. The following code shows how a MouseEventHandler class forces dynamic allocation.
class EventHandler { public: virtual ~EventHandler () {} }; class MouseEventHandler : public EventHandler // Note inheritance { protected: ~MouseEventHandler () {} // A protected virtual destructor. public: MouseEventHandler () {} // Public Constructor. }; int main (void) { MouseEventHandler m; // A scoped variable is not allowed as destructor is protected. EventHandler *e = new MouseEventHandler (); // Dynamic allocation is allowed delete e; // Polymorphic delete. Does not leak memory. }
Another way to force dynamic allocation is to prevent direct access to the constructor and instead provide a static function instance() to return a dynamically allocated object. It is in many ways similar to the Singleton design pattern. Moreover, it is not strictly necessary to use polymorphic delete to reclaim memory. A member function destroy() can serve the purpose saving the space required for a v-table pointer.
class MouseEventHandler // Note no inheritance { protected: MouseEventHandler () {} // Protected Constructor. ~MouseEventHandler () {} // A protected, non-virtual destructor. public: static MouseEventHandler * instance () { return new MouseEventHandler(); } void destroy () { delete this; } // Reclaim memory. };
An opposite extreme of this idiom is to force scoped variable (a.k.a. automatic variable) only. It can be achieved using a private new operator.
class ScopedLock { private: static void * operator new (unsigned int size); // Disallow dynamic allocation static void * operator new (unsigned int size, void * mem); // Disallow placement new as well. }; int main (void) { ScopedLock s; // Allowed ScopedLock * sl = new ScopedLock (); // Standard new and nothrow new are not allowed. void * buf = ::operator new (sizeof (ScopedLock)); ScopedLock * s2 = new(buf) ScopedLock; // Placement new is also not allowed }
ScopedLock object can't be allocated dynamically with standard uses of new operator, nothrow new, and the placement new.
Known Uses
Related Idioms
References
- Concrete Data Type - J. Coplien.
Non-Virtual Interface
Intent
- To modularize/refactor common before and after code fragments (e.g., invariant checking, acquiring/releasing locks) for an entire class hierarchy at one location.
Also Known As
- Template Method - a more generic pattern, from the Gang of Four's Design Patterns book.
Motivation
Pre- and post-condition checking is known to be a useful object-oriented programming technique particularly at development time. Pre- and post-conditions ensure that invariants of a class hierarchy (and in general an abstraction) are not violated at designated points during execution of a program. Using them at development time or during debug builds help in catching any violations earlier. To maintain consistency and ease of maintenance of such pre- and post-conditions, they should be ideally modularized at one location. In the context of a class hierarchy, where its invariants must be held before and after every method in the subclasses, modularization becomes important.
Similarly, acquiring and releasing locks on a data structure common to a class hierarchy can be considered as a pre- and post-condition, which must be ensured even at production time. It is useful to separate the responsibility of lock acquiring and releasing from subclasses and put it at one place - potentially in the base class.
Solution and Sample Code
Non-Virtual Interface (NVI) idiom allows us to refactor before and after code fragments at one convenient location - the base class. NVI idiom is based on 4 guidelines outlined by Herb Sutter in his article named "Virtuality"[2]. Quoting Herb:
- Guideline #1: Prefer to make interfaces nonvirtual, using Template Method design pattern.
- Guideline #2: Prefer to make virtual functions private.
- Guideline #3: Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected.
- Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual. - Quote complete.
Here is some code that implements NVI idiom following the above 4 guidelines.
class Base { private: ReaderWriterLock lock_; SomeComplexDataType data_; public: void read_from( std::istream & i) { // Note non-virtual lock_.acquire(); assert(data_.check_invariants() == true); // must be true read_from_impl(i); assert(data_.check_invariants() == true); // must be true lock_.release(); } void write_to( std::ostream & o) const { // Note non-virtual lock_.acquire(); write_to_impl(o); lock_.release(); } virtual ~Base() {} // Virtual because Base is a polymorphic base class. private: virtual void read_from_impl( std::istream & ) = 0; virtual void write_to_impl( std::ostream & ) const = 0; }; class XMLReaderWriter : public Base { private: virtual void read_from_impl (std::istream &) { // Read XML. } virtual void write_to_impl (std::ostream &) const { // Write XML. } }; class TextReaderWriter : public Base { private: virtual void read_from_impl (std::istream &) {} virtual void write_to_impl (std::ostream &) const {} };
The above implementation of the base class captures several design intents that are central to achieving the benefits of NVI idiom. This class intends to be used as a base class and therefore, it has a virtual destructor and some pure virtual functions (read_from_impl, write_to_impl), which must be implemented by all the concrete derived classes. The interface for clients (i.e., read_from and write_to) is separate from the interface for the subclasses (i.e. read_from_impl and write_to_impl). Although the read_from_impl and write_to_impl are two private functions, the base class can invoke the corresponding derived class functions using dynamic dispatch. These two functions give the necessary extension points to a family of derived classes. However, they are prevented from extending the client interface (read_from and write_to). Note that, it is possible to call interface for clients from the derived classes, however, it will lead to recursion. Finally, NVI idiom suggests use of exactly one private virtual extension point per public non-virtual function.
Clients invoke only the public interface, which in turn invokes virtual *_impl functions as in the Template Method design pattern. Before and after invoking the *_impl functions, lock operations and invariant checking operations are performed by the base class. In this way, hierarchy wide before and after code fragments can be put together at one place, simplifying maintenance. Clients of the Base hierarchy still get polymorphic behavior even though they don't invoke virtual functions directly. Derived classes should ensure that direct access to the implementation functions (*_impl) is disallowed to the clients by making them private in the derived class as well.
Consequences
Using NVI idiom may lead to fragile class hierarchies if proper care is not exercised. As described in [1], in Fragile Base Class (FBC) interface problem, subclass's virtual functions may get accidentally invoked when base class implementation changes without notice. For example, the following code snippet (inspired by [1]) uses NVI idiom to implement CountingSet, which has Set as a base class.
class Set { std::set<int> s_; public: void add (int i) { s_.insert (i); add_impl (i); // Note virtual call. } void addAll (int * begin, int * end) { s_.insert (begin, end); // --------- (1) addAll_impl (begin, end); // Note virtual call. } private: virtual void add_impl (int i) = 0; virtual void addAll_impl (int * begin, int * end) = 0; }; class CountingSet : public Set { private: int count_; virtual void add_impl (int i) { count_++; } virtual void addAll_impl (int * begin, int * end) { count_ += std::distance(begin,end); } };
The above class hierarchy is fragile in the sense that during maintenance, if the implementation of the addAll function (indicated by (1)) is changed to call public non-virtual add function for every integer from begin to end, then the derived class, CountingSet, breaks. As addAll calls add, the derived class's extension point add_impl is called for every integer and finally addAll_impl is also called couting the range of integers twice, which silently introduces a bug in the derived class! The solution is to observe a strict coding discipline of invoking exactly one private virtual extension point in any public non-virtual interface of the base class. However, the solution depends on programmer discipline and hence difficult to follow in practice.
Note how NVI idiom treats each class hierarchy as a tiny (some may like to call trivial) object-oriented framework, where inversion of control (IoC) flow is commonly observed. Frameworks control the flow of the program as opposed to the functions and classes written by the client, which is why it is known as inversion of control. In NVI, the base class controls the program flow. In the example above, the Set class does the required common job of insertion before calling the *_impl virtual functions (the extension points). The Set class must not invoke any of its own public interface to prevent the FBC problem.
Finally, NVI idiom leads to a moderate degree of code bloat in the class hierarchy as the number of functions double when NVI is applied. Size of the refactored code in the base class should be substantial to justify the use of NVI.
Known Uses
Related Idioms
- Interface Class
- Thread-Safe Interface, from Pattern-Oriented Software Architecture (volume 2) by Douglas Schmidt et al.
- Public Overloaded Non-Virtuals Call Protected Non-Overloaded Virtuals [1]
References
[1] Selective Open Recursion: Modular Reasoning about Components and Inheritance - Jonathan Aldrich, Kevin Donnelly.
[2] Virtuality! -- Herb Sutter
[3] Conversations: Virtually Yours -- Jim Hyslop and Herb Sutter
[4] Should I use protected virtuals instead of public virtuals? -- Marshall Cline
Named Constructor
Intent
- To have a readable and intuitive way of creating objects of a class
- To impose certain constraints while creating objects of a class
Also Known As
Motivation
In C++, constructors are distinguished from each other only based on the type, the order and the number of parameters. Of course when a class has multiple constructors, each constructor has a different purpose. However, in C++ it is hard to capture that "semantic" difference in the interface of the class because all the constructors have the same name and only parameters can distinguish between them. Reading code with lots of constructor calls only differing in the type/order/number of parameters is quite unintuitive except for the original developer of the class. Named constructor idiom addresses the problem.
Solution and Sample Code
The named constructor idiom uses a set of static member functions with meaningful names to create objects instead of constructors. Constructors are either private or protected and clients have access only to the public static functions. The static functions are called "named constructors" as each unique way of creating an object has a different intuitive name. Consider the example below:
class Game { public: static Game createSinglePlayerGame() { return Game(0); } // named constructor static Game createMultiPlayerGame() { return Game(1); } // named constructor protected: Game (int game_type); }; int main(void) { Game g1 = Game::createSinglePlayerGame(); // Using named constructor Game g2 = Game(1); // multiplayer game; without named constructor (does not compile) }
Without using the named constructor idiom in the class above, it is difficult to convey the meaning of what Game(1) and Game(0) means. The idiom makes it loud and clear! Additionally, it is possible to put certain constraints on the object creation process using this idiom. For example, named constructors could always create an object dynamically using new. In such a case, Resource Return idiom could be helpful.
Known Uses
Related Idioms
References
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8
Polymorphic Exception
Intent
- To create an exception object polymorphically
- To decouple a module from the concrete details of the exceptions it may throw
Also Known As
Motivation
Dependency Inversion Principle (DIP), a popular object-oriented software design guideline states that higher level modules should not depend directly on lower level modules. Instead, both should depend on common abstractions (captured in the form of well-defined interfaces). For example, an object of type Person (say John) should not create and use an object of type HondaCivic but instead John should simply commit to a Car interface, which is an abstract base class of HondaCivic. This allows John to upgrade to a Corvette easily in future without any changes to the class Person. John can be "configured" with a concrete instance of a car (any car) using dependency injection technique. Use of DIP leads to flexible and extensible modules that are easy to unit test. Unit testing is simplified by DIP because real objects can be easily replaced with mock objects using dependency injection.
However, there are several occasions when DIP is violated: (1) while using the Singleton pattern and (2) while throwing exceptions! Singleton pattern breaks DIP because it forces the use of the concrete class name while accessing the static instance() function. A singleton should be passed as a parameter while calling a function or a constructor. A similar situation arises while dealing with exceptions in C++. The throw clause in C++ requires a concrete type name (class) to raise an exception. For example,
throw MyConcreteException("Big Bang!");
Any module that throws exceptions like this immediately results into a violation of DIP. Naturally, it is harder to unit test such a module because real exception objects cannot easily be replaced with mock exception objects. A solution like the one below fails miserably as throw in C++ uses static typing and knows nothing about polymorphism.
struct ExceptionBase { }; struct ExceptionDerived : ExceptionBase { }; void foo(ExceptionBase& e) { throw e; // Uses static type of e while rasing an exception. } int main (void) { ExceptionDerived e; try { foo(e); } catch (ExceptionDerived& e) { // Exception raised in foo does not match this catch. } catch (...) { // Exception raised in foo is caught here. } }
Polymorphic exception idiom addresses the issue.
Solution and Sample Code
Polymorphic exception idiom simply delegates the job of raising the exception back to the derived class using a virtual function raise()
struct ExceptionBase { virtual void raise() { throw *this; } virtual ~ExceptionBase() {} }; struct ExceptionDerived : ExceptionBase { virtual void raise() { throw *this; } }; void foo(ExceptionBase& e) { e.raise(); // Uses dynamic type of e while raising an exception. } int main (void) { ExceptionDerived e; try { foo(e); } catch (ExceptionDerived& e) { // Exception raised in foo now matches this catch. } catch (...) { // not here anymore! } }
The throw statement has been moved into virtual functions. The raise function invoked in function foo is polymorphic and selects the implementation in either ExceptionBase or ExceptionDerived class depending upon what is passed as a parameter (dependency injection). Type of *this is obviously known at compile-time, which results into raising a polymorphic exception. The structure of this idiom is very similar to that of Virtual Constructor idiom.
Known Uses
Related Idioms
References
Metafunction
Intent
- To encapsulate a complex type computation algorithm
- To generate a type using compile-time type selection techniques
Also Known As
Motivation
Templates is a powerful feature of C++, which can be used to perform arbitrary computations at compile-time, which is known as template metaprogramming. Some of the basic examples of the computations performed at compile-time are: (1) selection of a type based on compile-time constants or (2) computing factorial of a number. As a matter of fact, C++ templates is a turing complete sub-language of C++. Metafunction idiom is the principle way of writing compile-time algorithms in C++.
Algorithms -- compile-time or run-time -- should be encapsulated so that they are easier to use and reuse. Conventionally, run-time algorithms are encapsulated in functions that are invoked, obviously, at run-time. Metafunctions, on the other hand, are compile-time analogs of run-time functions. Traditional functions accept values/objects as parameters and return values/objects. However, metafunctions accept types and compile-time constants as parameters and return types/constants.
Solution and Sample Code
A metafunction, contrary to its name, is a class template. Implementation of metafunctions is often based on template specializations. For example, consider the following IF metafunction, which is compile-time equivalent of run-time if statement. Depending upon the value of the first parameter, IF metafunction yields either an int or a long in the example below.
template <bool, class L, class R> struct IF { typedef R type; }; template <class L, class R> struct IF<true, L, R> { typedef L type; }; IF<false, int, long>::type i; // is equivalent to long i; IF<true, int, long>::type i; // is equivalent to int i;
Factorial metafunction below is another example showing how a recursive factorial computation algorithm can be encapsulated using C++ templates. This metafunction yields an integral value rather than a type.
template <int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; }; template <> struct Factorial<0> { enum { value = 1 }; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void foo() { int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1 }
Metafunction and Type Generator
Metafunction is a more general idiom than the type generator idiom. The intent of metafunction idiom is to encapsulate compile-time computation where as, type generator simplifies specification of a type. Metafunctions that produce type(s) as a result of a compile-time computation are all type generators, albeit more complex. However, not every metafunction is a type generator. For example, the Factorial metafunction shown before produces an integral value, not a type, at the end of the computation. Generally, metafunctions are implemented using compile-time control structures or other metafunctions unlike type generators.
Libraries such as Boost.MPL provide a large collection of metafunctions and compile-time data structures to simplify C++ template metaprogramming.
Higher order metafunctions
These are metafunctions that accept other metafunctions as parameters and use them during computation. This is conceptually is similar a function accepting a pointer to another function or a function object as a parameter at run-time. Only difference is that metafunctions exist only at compile-time. boost::mpl::transform is an example of such a higher order metafunction.
Known Uses
Related Idioms
References
A Deeper Look at Metafunctions -- David Abrahams and Aleksey Gurtovoy
Type Generator
Intent
- To simplify creation of complex template-based types
- To synthesize a new type or types based on template argument(s)
- To localize default policies when policy-based class design is used
Also Known As
Templated Typedef Idiom
Motivation
Class templates designed using policy-based class design technique, often result into very flexible templates with multiple type parameters. One downside of such class templates is that, too many type parameters must be provided when their instances are created. Default template parameters come handy in such cases. However, all the intermediate template parameters need to be specified anyways when the last template parameter (policy class) is different from the default.
For example, consider a case where special purpose allocators are used with standard C++ containers. GNU C++ compiler provides many special purpose allocators in namespace __gnu_cxx as extensions of the standard C++ library. Consider the following standard map template instantiation with malloc allocator.
std::map <std::string, int, less<std::string>, __gnu_cxx::malloc_allocator<std::string> >
A variation of the above map using float instead of an int requires all the unrelated type parameters to be mentioned again.
std::map <std::string, float, less<std::string>, __gnu_cxx::malloc_allocator<std::string> >
Type generator idiom is used to reduce code bloat in such cases.
Solution and Sample Code
In type generator idiom, common (invariant) parts of a family of type definitions are collected together in a structure, whose sole purpose is to generate another type. For example, consider the Directory template shown below.
template <class Value> struct Directory { typedef std::map <std::string, Value, std::less<std::string>, __gnu_cxx::malloc_allocator<std::string> > type; }; Directory<int>::type // gives a map of string to integers. Directory<float>::type // gives a map of string to floats.
An extra level of indirection (struct Directory) is used to capture the invariant part and one or two template parameters are left open for customization. A type generator usually consolidates a complicated type expression into a simple one. A type generator can be used to generate more than one type by simply adding more typedefs.
For example, consider how standard STL algorithms are applied to maps.
Directory<int>::type age; // This is a map. transform(age.begin(), age.end(), std::ostream_iterator<string>(std::cout, "\n"), _Select1st<std::map<std::string, int>::value_type> ());
An adapter that transforms map's value_type, which is a pair, into the first element of the pair. _Select1st does the job of adapter in the example above. Its type is needlessly complex with ample opportunity of typing it wrong when repeated multiple times. Instead, type generator idiom simplifies type specification of the adapter considerably.
template <class Value> struct Directory { typedef map <string, Value, less<string>, __gnu_cxx::malloc_allocator<std::string> > type; typedef _Select1st<typename type::value_type> KeySelector; typedef _Select2nd<typename type::value_type> ValueSelector; }; Directory<int>::type age; // This is a map. transform(age.begin(), age.end(), std::ostream_iterator<string>(std::cout, "\n"), Directory<int>::KeySelector());
Finally, type generator can be used to conveniently change the invariant type parameters, if needed. For example, changing malloc_allocator to debug_allocator throughout the program. The main reason why you might sometimes want to change it is to get more useful information from bounds-checking or leak-detection tools while debugging. Using type generators such a program-wide effect can be achieved by simply changing it at one place.
Known Uses
- Boost.Iterator library
Related Idioms
References
[1] Type Generator
[2] Policy Adaptors and the Boost Iterator Adaptor Library -- David Abrahams and Jeremy Siek
[3] Template Typedef -- Herb Sutter
[4] The New C++: Typedef Templates -- Herb Sutter
Template Typedef
Please see the Type Generator idiom.
Object Generator
Intent
- To simplify creation of objects without explicitly specifying their types. (This is not factory method pattern)
Also Known As
Motivation
In C++ template programming, types of objects can get really large and incomprehensible even in small programs. For example, following type (Wrapper) is a standard unary function object that wraps the member function read_line in class File.
struct File { int read_line (std::string); }; typedef std::mem_fun1_t<int, File, std::string> Wrapper;
Reading a collection of files using for_each STL algorithm, looks like below without object generators.
void read_lines(std::vector<File *> files) { typedef std::mem_fun1_t<int, File, std::string> Wrapper; std::string arg; for_each(files.begin(), files.end(), std::binder2nd<Wrapper>(Wrapper(&File::read_line), arg)); }
The above code is pretty much unreadable and more bloated than necessary. Even typedefs don't improve readability as placeholder typedefs like Wrapper are distracting. The object generator idiom alleviates the situation.
Solution and Sample Code
In object generator idiom, a template function is created whose only job is to construct a new object from its parameters. It is based on a useful property that only function templates have but class templates don't: The type parameters of a function template are deduced automatically from its actual parameters. For example, consider a simple object generator defined in STL: make_pair.
template <class T, class U> std::pair <T, U> make_pair(T t, U u) { return std::pair <T, U> (t,u); }
make_pair returns an instance of the pair template depending on the actual parameters of the make_pair function. For example, make_pair(1,1.0) creates an object of type: std::pair<int, double> by automatically deducing the types of the objects being passed to the object generator function. make_pair comes particularly handy when generated pair object need not be stored in a local variable.
map <int, double> m; m.insert (make_pair(1,1.0)); // No need to know how pair template is instantiated.
C++ standard library defines several object generators to avoid code bloat. std::bind2nd and std::mem_fun are two such standard object generators that can be used to avoid code bloat in the example shown in the motivation section above.
void read_lines(std::vector<File *> files) { std::string arg; for_each(files.begin(), files.end(), bind2nd(mem_fun(&File::read_line), arg)); }
Known Uses
C++ standard library (mem_fun, make_pair, bind1st, bind2nd etc.)
Related Idioms
References
Copy-on-write
Intent
A kind of lazy copy optimization.
Also Known As
- COW
- Lazy copy
Motivation
Copying an object can sometimes cause a performance penalty. If objects are frequently copied but infrequently modified later, copy-on-write can provide significant optimization. To implement copy-on-write, a smart pointer to the real content is used to encapsulate the object's value, and on each modification an object reference count is checked; if the object is referenced more than once, a copy of the content is created before modification.
Solution and Sample Code
#ifndef COWPTR_HPP #define COWPTR_HPP #include <boost/shared_ptr.hpp> template <class T> class CowPtr { public: typedef boost::shared_ptr<T> RefPtr; private: RefPtr m_sp; void detach() { T* tmp = m_sp.get(); if( !( tmp == 0 || m_sp.unique() ) ) { m_sp = RefPtr( new T( *tmp ) ); } } public: CowPtr(T* t) : m_sp(t) {} CowPtr(const RefPtr& refptr) : m_sp(refptr) {} CowPtr(const CowPtr& cowptr) : m_sp(cowptr.m_sp) {} CowPtr& operator=(const CowPtr& rhs) { m_sp = rhs.m_sp; // no need to check for self-assignment with boost::shared_ptr return *this; } const T& operator*() const { return *m_sp; } T& operator*() { detach(); return *m_sp; } const T* operator->() const { return m_sp.operator->(); } T* operator->() { detach(); return m_sp.operator->(); } }; #endif //COWPTR_HPP
This implementation of copy-on-write is generic, but apart from the inconvenience of having to refer to the inner object through smart pointer dereferencing, it suffers from at least one drawback: classes that return references to their internal state, like
char & String::operator[](int)
can lead to unexpected behaviour.[1]
Consider the following code snippet
CowPtr<String> s1 = "Hello"; char &c = s1->operator[](4); // Non-const detachment does nothing here CowPtr<String> s2(s1); // Lazy-copy, shared state c = '!'; // Uh-oh
The intention of the last line is to modify the original string s1, not the copy, but as a side effect s2 is also accidentally modified.
A better approach is to write a custom copy-on-write implementation which is encapsulated in the class we want to lazy-copy, transparently to the user. In order to fix the problem above, one can flag objects that have given away references to inner state as "unshareable"—in other words, force copy operations to deep-copy the object. As an optimisation, one can revert the object to "shareable" after any non-const operations that do not give away references to inner state (for example, void String::Clear()), because client code expects such references to be invalidated anyway.[1]
Known Uses
- Active Template Library
- Many Qt classes
Related Idioms
References
Recursive Type Composition
Intent
Also Known As
Motivation
Solution and Sample Code
Known Uses
Related Idioms
References
Compile Time Recursive Objects in C++ - Jaakko Jarvi
GNU Free Documentation License
Version 1.2, November 2002
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.
A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.
The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, a