Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there no std::protect?

Tags:

Why is there no std::protect to use together with std::bind in C++11?

Boost.Bind provides a boost::protect helper that wraps its argument so that boost::bind does not recognize and evaluate it. std::[c]ref would be a good enough replacement most of the times, except that it won't take an rvalue as argument.

For a concrete example, consider the following artificial situation:

#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))); } 
like image 473
K-ballo Avatar asked Aug 29 '13 19:08

K-ballo


People also ask

Can you get STD from kissing?

Although kissing is considered to be low-risk when compared to intercourse and oral sex, it's possible for kissing to transmit CMV, herpes, and syphilis. CMV can be present in saliva, and herpes and syphilis can be transmitted through skin-to-skin contact, particularly at times when sores are present.

Is there a pill to prevent STDs?

Birth control methods like the pill, patch, ring, and IUD are very effective at preventing pregnancy, but they do not protect against STDs and HIV. The most reliable way to avoid STDs is to not have vaginal, anal, or oral sex.


1 Answers

Well, I'm not aware of why it wasn't implemented. Perhaps it wasn't proposed, or perhaps there were some subtle gotchas.

That said, I think you can write it pretty easily

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

The two versions of protect are so that non-bind expressions are not wrapped (they just pass through). Everything else is passed by move/copy to the protect_wrapper, which simply inherits from the type. This allows the type's functions to pass through, or for it to convert to the type.

It makes a copy/move however, so it can be safely used with rvals. And since it only protects types that are bind_expressions, it minimizes the amount of copying that has to occur.

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;  } 
like image 91
Dave S Avatar answered Oct 08 '22 03:10

Dave S