Обърнете внимание, че предпочитаната терминология (т.е. тази, която ще бъде в бъдещите версии на спецификацията) сега е референция за препращане.
Както казвате, препращащата препратка работи само с приспадане на типа в шаблон на функция. Във вашия случай, когато кажете T&&
, T
е int
. Не може да бъде int&
, защото е изрично посочено във вашата инстанция Bar
. Като такива правилата за свиване на препратки не могат да възникнат, така че не можете да направите перфектно препращане.
Ако искате да направите перфектно препращане в членска функция като тази, трябва да имате шаблон за членска функция:
template <typename U>
void foo(U&& arg)
{
std::forward<U>(arg); //actually do something here
}
Ако абсолютно трябва U
да има същия неквалифициран тип като T
, можете да направите 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 be the same as T");
std::forward<U>(arg); //actually do something here
}
std::decay
може да е твърде агресивен за вас, тъй като ще разпадне типовете масиви до указатели. Ако това не е това, което искате, можете да напишете своя собствена проста черта:
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>>;
Ако имате нужда от променлива версия, можем да напишем черта are_equiv
. Първо се нуждаем от черта, за да проверим дали всички характеристики в глутницата са верни. Ще използвам метода bool_pack
:
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...>;
Тогава имаме нужда от нещо, за да проверим дали всяка двойка типове в Ts...
и Us...
удовлетворява is_equiv
. Не можем да вземем два пакета с параметри като аргументи на шаблона, така че ще използвам std::tuple, за да ги разделя (можете да използвате възел за наблюдение или вместо това да разделите пакета по средата, ако желаете):
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>...>
{};
Тогава можем да използваме това като:
static_assert(are_equiv<std::tuple<Ts...>,std::tuple<Us...>>::value,
"Us must be equivalent to Ts");
person
TartanLlama
schedule
01.06.2015