为什么在C++ 11中没有std::protect
和它一起使用?std::bind
Boost.Bind提供了一个boost::protect
帮助器,它包装了它的参数,因此boost::bind
无法识别和评估它.std::[c]ref
在大多数情况下,它将是一个足够好的替代品,除了它不会将右值作为参数.
举一个具体的例子,考虑以下人为情况:
#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)));
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*e S 15
好吧,我不知道它为什么没有实施.也许它没有提出,或者也许有一些微妙的陷阱.
那就是说,我认为你可以很容易地写出来
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));
}
Run Code Online (Sandbox Code Playgroud)
保护的两个版本是这样的,非绑定表达式不会被包装(它们只是通过).其他所有内容都通过移动/复制传递给protect_wrapper
,只是从类型继承.这允许类型的函数通过,或者转换为类型.
然而,它会进行复制/移动,因此可以安全地与rvals一起使用.因为它只保护bind_expressions类型,所以它最大限度地减少了必须发生的复制量.
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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1601 次 |
最近记录: |