c++ - Passing reference as lvalue/rvalue depending on function signature -


let's have data :

struct bar {}; 

i need wrap function , feed data.

template<typename f> void foo(f f) {     bar bar;     f(bar); } 

as can see in trivial example:

  • bar not temporary
  • i don't need after calling f

i want support multiple function signatures, such :

foo([](bar){}); // (1) foo([](bar&){}); // (2) foo([](bar&&){}); // (3) 

however gcc complains :

f(bar); // (3) : cannot bind 'bar' lvalue 'bar&&' f(std::move(bar)); // (2) : no match call ... 

how both ?

struct barish{   bar&b;   operator bar&&()&&{return std::move(b);}   operator bar&()&&{return b;} }; 

then f(barish{bar}).

the downside if f takes deduced parameter, gets barish not bar.

assuming have sfinae friendly result_of...

template<class...>struct voider{using type=void;}; template<class...ts>using void_t=typename voider<ts...>::type;  template<class...>struct types{using type=types;};  namespace details{   template<template<class...>class z,class types,class=void>   struct can_apply:std::false_type{};   template<template<class...>class z,class...ts>   struct can_apply<z,types<ts...>,void_t<z<ts...>>>:     std::true_type   {}; }; template<template<class...>class z,class...ts> using can_apply=details::can_apply<z,types<ts...>>;  template<class sig> using result_of_t=typename std::result_of<sig>::type;  template<class sig> using can_invoke=can_apply<result_of_t,sig>; 

and can test.

template<typename f> void foo(f&& f,std::true_type) {   bar bar;   std::forward<f>(f)(std::move(bar)); }  template<typename f> void foo(f&& f,std::false_type) {   bar bar;   std::forward<f>(f)(bar); }   template<typename f> void foo(f f) {   foo(std::forward<f>(f),can_apply<f(bar&&)>{}); } 

and done. (there may typos above, code written on phone)


Comments

Popular posts from this blog

javascript - AngularJS custom datepicker directive -

javascript - jQuery date picker - Disable dates after the selection from the first date picker -