c++ - Universal reference with templated class -
example:
template <typename t> class bar { public: void foo(t&& arg) { std::forward<t>(arg); } }; bar<int> bar; bar.foo(10); // works int a{ 10 }; bar.foo(a); // error c2664: cannot convert argument 1 'int' 'int &&'
it seems universal references works only templated functions , only type deduction, right? make no sense use class? , using of std::forward
makes sense in case?
note preferred terminology (i.e. 1 in future versions of spec) forwarding reference.
as say, forwarding reference works type deduction in function template. in case, when t&&
, t
int
. can't int&
because has been explicitly stated in bar
instantiation. such, reference-collapsing rules can't occur, can't perfect forwarding.
if want perfect forwarding in member function that, need have member function template:
template <typename u> void foo(u&& arg) { std::forward<u>(arg); //actually here }
if absolutely need u
have same unqualified type t
, can static_assert
:
template <typename u> void foo(u&& arg) { static_assert(std::is_same<std::decay_t<u>,std::decay_t<t>>::value, "u must same t"); std::forward<u>(arg); //actually here }
std::decay
might bit aggressive decay array types pointers. if that's not want, write own simple trait:
template <typename t> using remove_cv_ref = std::remove_cv_t<std::remove_reference_t<t>>; template <typename t, typename u> using is_equiv = std::is_same<remove_cv_ref<t>, remove_cv_ref<u>>;
if need variadic version, can write are_equiv
trait. first need trait check if traits in pack true. i'll use bool_pack
method:
namespace detail { template<bool...> struct bool_pack; template<bool... bs> using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>; } template <typename... ts> using all_true = detail::all_true<ts::value...>;
then need check if each pair of types in ts...
, us...
satisfy is_equiv
. can't take 2 parameter packs template arguments, i'll use std::tuple separate them (you use sentinel node, or split pack halfway through instead if wanted):
template <typename ttuple, typename utuple> struct are_equiv; template <typename... ts, typename... us> struct are_equiv <std::tuple<ts...>, std::tuple<us...>> : all_true<is_equiv<ts,us>...> {};
then can use like:
static_assert(are_equiv<std::tuple<ts...>,std::tuple<us...>>::value, "us must equivalent ts");
Comments
Post a Comment