c++ - page - ¿Por qué no hay std:: protect?
latex letter page size (1)
Bueno, no sé por qué no se implementó. Tal vez no fue propuesto, o tal vez hubo algunas trampas sutiles.
Dicho esto, creo que puedes escribirlo bastante fácilmente
template<typename T>
struct protect_wrapper : T
{
protect_wrapper(const T& t) : T(t)
{
}
protect_wrapper(T&& t) : T(std::move(t))
{
}
};
template<typename T>
typename std::enable_if< !std::is_bind_expression< typename std::decay<T>::type >::value,
T&& >::type
protect(T&& t)
{
return std::forward<T>(t);
}
template<typename T>
typename std::enable_if< std::is_bind_expression< typename std::decay<T>::type >::value,
protect_wrapper<typename std::decay<T>::type > >::type
protect(T&& t)
{
return protect_wrapper<typename std::decay<T>::type >(std::forward<T>(t));
}
Las dos versiones de protect son para que las expresiones no vinculantes no se envuelvan (solo pasan). Todo lo demás se pasa por mover / copiar a protect_wrapper
, que simplemente se hereda del tipo. Esto permite que las funciones del tipo pasen a través o que se conviertan al tipo.
Sin embargo, realiza una copia / movimiento, por lo que puede usarse de forma segura con rvals. Y como solo protege los tipos que son bind_expressions, minimiza la cantidad de copias que se deben producir.
int main()
{
//// Ok, with protect
auto bind_expr =
std::bind<int>(invoke_with_42{}
, protect(std::bind(&add, 1, std::placeholders::_1)));
std:: cout << bind_expr() << std::endl;
return 0;
}
¿Por qué no hay std::protect
para usar junto con std::bind
en C ++ 11 ?
Boost.Bind proporciona un ayudante boost::protect
que envuelve su argumento para que boost::bind
no lo reconozca ni lo evalúe. std::[c]ref
sería un buen reemplazo la mayoría de las veces, excepto que no tomará un valor de r como valor de argumento.
Para un ejemplo concreto, considere la siguiente situación artificial:
#include <type_traits>
#include <functional>
int add(int a, int b)
{ return a + b; }
struct invoke_with_42
{
template <typename FunObj>
auto operator()(FunObj&& fun_obj) const -> decltype((fun_obj(42)))
{ return fun_obj(42); }
};
int main()
{
//// Nested bind expression evaluated
//auto bind_expr =
// std::bind<int>(invoke_with_42{}
// , std::bind(&add, 1, std::placeholders::_1));
//// Compilation error, cref does not take rvalues
//auto bind_expr =
// std::bind<int>(invoke_with_42{}
// , std::cref(std::bind(&add, 1, std::placeholders::_1)));
//// Ok, inner_bind_expr must be kept alive
auto inner_bind_expr =
std::bind(&add, 1, std::placeholders::_1);
auto outer_bind_expr =
std::bind<int>(invoke_with_42{}, std::cref(inner_bind_expr));
//// Ok, with protect
//auto bind_expr =
// std::bind<int>(invoke_with_42{}
// , std::protect(std::bind(&add, 1, std::placeholders::_1)));
}