Add enable_if_lvalue

This commit is contained in:
Edward Hennis
2014-08-22 19:50:15 -04:00
committed by Tom Ritchford
parent 5c67f99ef9
commit 612bb71165

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_UTILITY_META_H_INCLUDED
#define BEAST_UTILITY_META_H_INCLUDED
#include <type_traits>
#include <beast/cxx14/type_traits.h> // <type_traits>
namespace beast {
@@ -60,6 +60,81 @@ struct static_sum<>
static_assert(static_sum<5, 2, 17, 0>::value == 24, "");
template <class T, class U>
struct enable_if_lvalue
: public std::enable_if
<
std::is_same<std::decay_t<T>, U>::value &&
std::is_lvalue_reference<T>::value
>
{
};
/** Ensure const reference function parameters are valid lvalues.
Some functions, especially class constructors, accept const references and
store them for later use. If any of those parameters are rvalue objects,
the object will be freed as soon as the function returns. This could
potentially lead to a variety of "use after free" errors.
If the function is rewritten as a template using this type and the
parameters references as rvalue references (eg. TX&&), a compiler
error will be generated if an rvalue is provided in the caller.
@code
// Example:
struct X
{
};
struct Y
{
};
struct Unsafe
{
Unsafe (X const& x, Y const& y)
: x_ (x)
, y_ (y)
{
}
X const& x_;
Y const& y_;
};
struct Safe
{
template <class TX, class TY,
class = beast::enable_if_lvalue_t<TX, X>,
class = beast::enable_if_lvalue_t < TY, Y >>
Safe (TX&& x, TY&& y)
: x_ (x)
, y_ (y)
{
}
X const& x_;
Y const& y_;
};
struct demo
{
void
createObjects ()
{
X x {};
Y const y {};
Unsafe u1 (x, y); // ok
Unsafe u2 (X (), y); // compiles, but u2.x_ becomes invalid at the end of the line.
Safe s1 (x, y); // ok
// Safe s2 (X (), y); // compile-time error
}
};
@endcode
*/
template <class T, class U>
using enable_if_lvalue_t = typename enable_if_lvalue<T, U>::type;
} // beast
#endif // BEAST_UTILITY_META_H_INCLUDED