шаблонный добавляемый класс с набором переменных - PullRequest
0 голосов
/ 22 октября 2019

Добрый день,

Я пытался реализовать класс, который мог бы суммировать все с помощью внутренней хранимой переменной _val, см. Ниже:

#include <utility>
#include <vector>
#include <cassert>

template <typename T>
class Addable {
    T _val;

  public:
    explicit Addable(T v) :_val(std::move(v)) {}

    template <typename ...Us>
    [[nodiscard]] constexpr T add(Us&& ...us) const
    {
        return (_val + ... + us);
    }

    template<typename U>
    [[nodiscard]] constexpr T add(U u) const
    {
        if constexpr (std::is_same_v<T, std::vector<U>>) {
            auto copy = _val;
            for (auto& n : copy) {
                n += u;
            }
            return copy;
        }
        else {
            return _val + u;
        }
    }
};


int main()
{
    using namespace std;

    assert(Addable<int>{42}.add() == 42);
    assert(Addable<int>{42}.add(1) == 43);
    assert(Addable<int>{42}.add(1, 1) == 44);
    assert(Addable<int>{2}.add(1, 1, 1, 1, 1) == 7);

    {
        vector v {2, 3};
        vector expected {3, 4};
        assert(Addable<vector<int>>{v}.add(1) == expected);
    }

    {
        vector v {2, 3};
        vector expected {5, 6};
//        assert(Addable<vector<int>>{v}.add(1, 2) == expected); // compile error...
    }

    return 0;
}

Класс работает - с сложить выражение с простым T как int здесь. - с T, как у std::vector, но только для одного U u.

Когда я пытаюсь добавить для каждого элемента вектора по одному из каждого из пакета с переменными значениями его сломал, чтоЯ сделал не так? ...

Ответы [ 2 ]

1 голос
/ 22 октября 2019

Эта перегрузка обрабатывает все ваши тестовые случаи:

template <typename ...Us>
[[nodiscard]] constexpr T add(Us&& ...us) const
{
    if constexpr (!sizeof...(us))
    {
        return _val;
    }
    else if constexpr (std::is_same_v<T, std::vector< std::common_type_t<Us...> > > )
    {  // [2]
        auto copy = _val;
        for (int& i : copy)
            i += (us + ...);
        return copy;
    }
    else
    {
        return (_val + ... + us);
    }
}

В блоке [2], который вызывается для T = vector, вам нужно перебирать все элементы в копии, и для каждого вы должныдобавить результат свертки (us + ...) из входных аргументов.

Live demo

0 голосов
/ 22 октября 2019

Когда я пытаюсь добавить для каждого элемента вектора один из каждого из пакета variadic, который он сломал, что я сделал не так? ..

Я не понимаю, чего именно вы хотите... в любом случае

С

Addable<vector<int>>{v}.add(1, 2)

вы звоните add() с двумя аргументами.

У вас есть две версии add():переменная типа «один» и тот, который получает один аргумент.

Таким образом, вызывая его с двумя аргументами, только переменная соответствует

template <typename ...Us>
[[nodiscard]] constexpr T add(Us&& ...us) const
{
    return (_val + ... + us);
}

но оператор + в _val + ... + us, где _val - это std::vector<int>, а значения us... - int с, не определено. Так что ошибка.

Если вы вызываете add() с одним аргументом, например

Addable<vector<int>>{v}.add(2)

, код скомпилирует (вызывая версию add(), которая управляет регистром std::vector)но, очевидно, assert() завершится неудачно при запуске скомпилированной программы.

...