...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
A number of compilers incorrectly
treat const lvalues of integral type as rvalues, and create an illegal temporary
when binding to an lvalue reference to const in some expressions. This could
result in creating an optional lvalue reference that is in fact bound to
an unexpected temporary rather than to the intended object. In order to prevent
hard to find run-time bugs, this library performs compile-time checks to
prevent expressions that would otherwise bind an optional reference to an
unexpected temporary. As a consequence, on certain compilers certain pieces
of functionality in optional references are missing. In order to maintain
a portability of your code across different compilers, it is recommended
that you only stick to the minimum portable interface of optional references:
prefer direct-initialization and copy assignment of optional references to
copy-initialization and assignment from T&
:
const int i = 0; optional<const int&> or1; optional<const int&> or2 = i; // caution: not portable or1 = i; // caution: not portable optional<const int&> or3(i); // portable or1 = optional<const int&>(i); // portable
Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program.
#include <cassert> const int global_i = 0; struct TestingReferenceBinding { TestingReferenceBinding(const int& ii) { assert(&ii == &global_i); } void operator=(const int& ii) { assert(&ii == &global_i); } void operator=(int&&) // remove this if your compiler doesn't have rvalue refs { assert(false); } }; int main() { const int& iref = global_i; assert(&iref == &global_i); TestingReferenceBinding ttt = global_i; ttt = global_i; TestingReferenceBinding ttt2 = iref; ttt2 = iref; }