...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
When using references the destructor isn't needed. By not assuming it implicitly, we allow capturing types with private or protected destructors by reference. For the sake of consistency, it must be specified when capturing by value as well.
The members of any
can be customized. By using free functions, we guarantee that we don't interfere
with anything that a user might want.
An earlier version of the library used the names _1
,
_2
, etc. instead of _a
, _b
,
etc. This caused a certain amount of confusion because the numbered placeholders
are already used with a somewhat different meaning by several other libraries
including Boost/Std Bind, Boost.Phoenix, and Boost.MPL. I eventually decided
that since the placeholders represented named parameters instead of positional
parameters, letters were more appropriate than numbers.
Boost.Function allows you to use boost::ref
to
store a reference to a function object. However, in the general case treating
references and values in the same way causes inconsistent behavior that is
difficult to reason about. If Boost.TypeErasure handled references like this,
then, when you copy an any
,
you would have no idea whether the new object is a real copy or just a new
reference to the same underlying object. Boost.Function can get away with
it, because it doesn't expose any mutating operations on the stored function
object.
Another method that has been proposed is only to keep a reference the first time.
int i = 2; any x = ref(i); any y = x; // makes a copy
Unfortunately, this doesn't handle all use cases, as there is no reliable
way to return such a reference from a function. In addition it adds overhead
whether it's needed or not, as we would have to add a flag to any to keep
track of whether or not it is storing a reference. (The alternate method
of storing this in the "clone
"
method in the vtable is impossibly complex to implement given the decoupled
vtables that Boost.TypeErasure uses and it still adds overhead.).