Шаблоны Variadic с прямой ссылкой и оператором + =

У меня есть функция, которая должна принимать несколько параметров и после добавления всех параметров в *this, operator+= перегружен и работает по одному параметру. Функция выглядит

template <typename T, typename U>
struct are_equal :
std::is_same<typename std::decay<T>::type, U>::type
{};

template<typename T>
template<typename... U>
std::enable_if_t<are_equal<U ..., Object<T>>::value>
Object<T>::addd(U &&... u)
{
//  *this += std::forward<U>(u)...;
}

Вероятно, у меня есть две проблемы.
1. Я думаю, что я должен изменить часть своего кода с type_traitsНо мои эксперименты не дают правильного результата.
Ошибка со строкой комментариев (где находится operator +=)

C2893 Не удалось специализировать шаблон функции ‘enable_if<_Test, _Ty> :: type Object :: addd (U &&…)»
C2672 ‘Object :: addd’: не найдена соответствующая перегруженная функция

  1. Проблема со словарем (?) В строке комментария:

    *this += std::forward<U>(u)...;
    

Ошибка:

Синтаксическая ошибка C2143: отсутствует ‘;’ до ‘…’

Синтаксическая ошибка C2059: «…»

C3520 ‘u’: пакет параметров должен быть расширен в этом контексте

Operator+= отлично работает для одного элемента (я уверен).

-1

Решение

Я предполагаю, что вы хотите, чтобы расширение пакета производило что-то вроде этого:

*this += std::forward<U>(u_1),
*this += std::forward<U>(u_2),
// ...
*this += std::forward<U>(u_n);

Причина по которой *this += std::forward<U>(u)...; не работает в том, что, грубо говоря, запятые, производимые расширением пакета (но не выражением сгиба, см. ниже) не может быть использован как операторы.

Классический обходной путь до C ++ 17 — использовать фиктивный массив:

using dummy_array = int[];
dummy_array{(*this += std::forward<U>(u), 0)..., 0};

Обратите внимание, что запятые, создаваемые этим расширением, не используются как операторы (а скорее как разделители инициализаторов элементов), поэтому указанное выше ограничение не применяется.

Первый , 0 в приведенном фрагменте позволяет нам игнорировать возвращаемый тип *this += blah,
Второй , 0 используется для поддержки пустых пакетов параметров (в противном случае была бы попытка создать пустой массив, что недопустимо).

Псевдоним типа необходим, потому что компилятор не позволит вам использовать int[]{blah, blah} непосредственно.

В качестве альтернативы using, вы могли бы использовать что-то вроде

std::enable_if_t<1, int[]>{(std::cout << p, 0)..., 0};

Другой вариант — создать реальный массив вместо временного:

int dummy_array[]{(std::cout << p, 0)..., 0};
(void)dummy_array;

Но мне это не очень нравится.


Если у вас есть C ++ 17, вы должны использовать сложить выражения вместо:

((*this += std::forward<U>(u)), ...);
4

Другие решения

Я думаю, что вы хотите следующее:

template <bool ... Bs> struct bools {};

template <bool ... Bs>
using all_of = std::is_same<bools<true, Bs...>, bools<Bs..., true>>;

template <typename T, typename ... Ts>
using are_equal = all_of<std::is_same<T, Ts>::value...>;

template<typename T>
template<typename... Us>
std::enable_if_t<are_equal<T, std::decay_t<Us>...>::value>
Object<T>::add(Us&&... u)
{
const int dummy[] = {0, ((*this += std::forward<Us>(u)), 0)...};
static_cast<void>(dummy);
}
2

По вопросам рекламы [email protected]