gpt4 book ai didi

c++ - 为什么没有std::protect?

转载 作者:IT老高 更新时间:2023-10-28 13:01:27 26 4
gpt4 key购买 nike

为什么在C++11中没有std::protectstd::bind一起使用?

Boost.Bind 提供了一个 boost::protect 帮助器来包装其参数,以便 boost::bind 无法识别和评估它. std::[c]ref 在大多数情况下是一个足够好的替代品,除了它不会将 rvalue 作为参数。

举个具体的例子,考虑如下人工情况:

#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)));
}

最佳答案

嗯,我不知道为什么没有实现。也许它没有被提议,或者可能有一些微妙的陷阱。

也就是说,我认为你可以很容易地写出来

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));
}

protect 的两个版本使得非绑定(bind)表达式不被包装(它们只是通过)。其他所有内容都通过移动/复制传递到 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;

}

关于c++ - 为什么没有std::protect?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18519087/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com