Barton-Nackman trick

From Wikipedia, the free encyclopedia

Barton-Nackman trick is a term originally used by the C++ standardization committee to refer to an idiom introduced by John Barton and Lee Nackman as Restricted Template Expansion.

[edit] The idiom

The idiom essence consists of defining (as opposed to simply declaring) one or more friend functions directly in a class template definition.

template<typename T>
class value_type
{
    friend bool operator==(const value_type<T> & a, const value_type<T> & b)
    {
        /* ... */
    }
};

When defined this way, the operator function is a non-template (and non-member) function. At the time the idiom was introduced (1994) the C++ language didn't allow function template overloading, so the above technique achieved the goal of providing a user-defined equality operator without writing

template<typename T>
bool operator==(const value_type<T> & a, const value_type<T> & b)
{
    /* ... */
}

which would have prevented (due to the absence of function template overloading) declaring any other operator== function in the same scope. The adjective restricted in the idiom name refers to the fact that the provided in-class function definition is restricted (only applies to) specializations of the given class template.

The term is sometimes mistakenly used to refer to the Curiously Recurring Template Pattern (CRTP). As explained above, the Barton-Nackman trick is clearly a distinct idiom; however its usage together with the CRTP allows reusable solutions such as the one illustrated below.

[edit] A typical usage in conjunction with the CRTP

namespace operators {

// A class template to express an equality comparison interface.
//
template<typename T> class equal_comparable
{
    friend bool operator==(T const &a, T const &b) { return  a.equal_to(b); }
    friend bool operator!=(T const &a, T const &b) { return !a.equal_to(b); }
};

} // namespace operators
// Class value_type wants to have == and !=, so it instantiates
// equal_comparable with itself as argument. Since
// operators::equal_comparable<value_type> is then an
// "associated class" of value_type the friend function names
// become findable via ADL.
//
class value_type : private operators::equal_comparable<value_type>
{
  public:
    bool equal_to(value_type const& rhs) const; // to be defined
};

When the compiler encounters the expression

 v1 == v2

where v1 and v2 are of type value_type, it finds the operator== defined in the base class template via argument dependent lookup.

The Barton-Nackman trick originally relied not on ADL but on a (now obsolete) C++ feature called "friend name injection", in which an in-class declaration of a friend function made the function name visible in the immediately surrounding namespace scope (possibly the global scope). When investigating the possibility of removing friend name injection from the C++ programming language, Barton and Nackman's idiom was found to be the only reasonable use of that language rule. Eventually, the rules for argument-dependent lookup were adapted to replace friend name injection by a less drastic mechanism, described above, that maintained the validity of Barton and Nackman's technique. It is worth noting that, as a consequence of this change, the expression

 operators::operator==(v1,v2)

is no longer valid, as the name operator== cannot be found in namespace operators via ordinary lookup. Likewise, it is important to note that the friend specifier is essential, even if the defined friend functions do not actually need to access non-public members of the befriending class.

[edit] References