Обратите внимание, что предпочтительная терминология (то есть та, которая будет использоваться в будущих версиях спецификации) теперь называется ссылка на пересылку.
Как вы говорите, ссылка на пересылку работает только с выводом типа в шаблоне функции. В вашем случае, когда вы говорите 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