Barton–Nackman trick
Barton–Nackman trick is a term coined by the C++ standardization committee to refer to an idiom introduced by John Barton and Lee Nackman as restricted template expansion.
The idiom
The idiom is characterized by an in-class friend function definition appearing in the base class template component of the curiously recurring template pattern.// A class template to express an equality comparison interface.
template
class EqualityComparable ;
// Class ValueType wants to have and !=, so it derives from
// EqualityComparable with itself as argument.
class ValueType : private EqualityComparable
When a class template like
EqualityComparable is instantiated, the in-class friend definitions produce nontemplate functions. At the time the idiom was introduced, the C++ language did not define a partial ordering for overloaded function templates and, as a result, overloading function templates often resulted in ambiguities. For example, trying to capture a generic definition for operator astemplate
bool operator
would essentially be incompatible with another definition like
template
bool operator
The Barton–Nackman trick, then, achieves the goal of providing a generic user-defined equality operator without having to deal with such ambiguities. The adjective restricted in the idiom name refers to the fact that the provided in-class function definition is restricted to specializations of the given class template.
The term is sometimes mistakenly used to refer to the curiously recurring template pattern. As explained above, the Barton–Nackman trick is, instead, a distinct idiom.
How it works
When the compiler encounters the expressionv1 v2, where v1 and v2 are of type ValueType, it attempts argument-dependent lookup for operator. This lookup includes consideration of friend functions declared in ValueType and its base classes. The Barton–Nackman trick originally relied not on ADL but on a 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. 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 adjusted to replace friend name injection by a less drastic mechanism, described above, that maintained the validity of Barton and Nackman's technique. As a consequence of this change, the expression
::operator is no longer valid, because qualified names aren't subject to ADL and friend declarations aren't found via ordinary lookup. Note, too, that the friend specifier is essential, even if the defined friend functions do not actually need to access nonpublic members of the befriending class.