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
Post a Comment