Ответ 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_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;
}