Как добавить арифметические операторы в std::array?

Я надеюсь унаследовать все методы, включая конструкторы std::array. я попробую

template<class T, size_t N>
class Vec : public array<T, N>
{
public:
    using array<T, N>::array;

    Vec operator+(Vec const& rhs) const
    {
        Vec res;
        transform(begin(), end(), rhs.begin(), res.begin(), plus);
        return res;
    }

};

Но получил некоторые ошибки компиляции.

  1. 'begin': подходящая перегруженная функция не найдена
  2. Я не могу сделать Vec<int, 2> v{1, 2}; как стандартные массивы, даже конструкторы наследуются.

Я могу что-то неправильно понять. Как решить эти ошибки. Любые лучшие идеи по добавлению арифметических операторов в std::array. Спасибо!


person user1899020    schedule 12.05.2019    source источник
comment
Кхм   -  person Lightness Races in Orbit    schedule 12.05.2019
comment
Во-первых, у вас есть опечатка (res должно быть rhs), во-вторых, std::plus - это тип, преобразование ожидает экземпляр этого типа, в-третьих, вам нужно использовать this-› перед началом и концом (что-то о двухфазном поиске, я думаю?). В-четвертых, что сказала Лайтнесс. Удалите использование массива‹T,N›::array, чтобы исправить инициализацию скобки (я понятия не имею, почему, но я думаю, что это связано с тем, что массив не имеет определяемого пользователем ctor?) ... Думаю, теперь это работает?   -  person Borgleader    schedule 12.05.2019
comment
Конечно, было бы здорово, если бы это был минимально воспроизводимый пример, поэтому любой, кто хочет скопировать/вставить его, не должен был поставлять все остальное.   -  person Retired Ninja    schedule 12.05.2019
comment
Будьте осторожны с stackoverflow.com/questions/2034916/ Я не думаю, что это применимо, но я всегда использую has-a container вместо is-a container, на всякий случай кто-то пытается расширить класс.   -  person Kenny Ostrom    schedule 12.05.2019


Ответы (2)


Хорошо, подождите, причина сложная, но не бойтесь, решение простое. Читать дальше.

array — это шаблон, поэтому члены класса array<T, N> неизвестны до создания экземпляра шаблона (помните, что шаблон может быть специализированным). И поскольку begin кажется независимым от каких-либо параметров шаблона, его имя разрешается на первом этапе поиска, до создания экземпляра array<T, N>, то есть до того, как члены array<T, N> станут известны. Вот почему вы получаете begin не найдено или аналогичную ошибку.

Простое решение — использовать this->begin. Таким образом, begin будет разрешено на втором этапе поиска (после создания экземпляра std::array<T, N>), потому что теперь ясно, что begin может быть членом унаследованного класса шаблона.

Кроме того, plus должно быть plus<>{} или plus{} в C++17.

И рекомендация: старайтесь избегать using namespace std Почему использование пространства имен std считается плохой практикой ?

Двухэтапный поиск - требуется объяснение

person bolov    schedule 12.05.2019
comment
Спасибо, мне все еще интересно, почему нельзя использовать агрегатную инициализацию Vec<int, 2> v{1, 2};. Я использую VS2017. - person user1899020; 12.05.2019
comment
Я использую пространство имен std в своем пространстве имен. Не уверен, что это нормально или все еще плохая практика. - person user1899020; 12.05.2019
comment
@ user1899020, потому что Vec не является агрегатом - person bolov; 12.05.2019
comment
stackoverflow.com/questions/24280521/ На тему использования пространства имен std , шаблоны все равно должны быть в шапке, верно? Поэтому это не ограничивается вашей единицей компиляции. Вы вынуждаете всех, кто использует это, помещать все std в свое пространство имен. Или вы можете написать std:: несколько раз, что кажется разумным бременем. - person Kenny Ostrom; 12.05.2019

Если вам нужно только добавить арифметические операции для std::array, я не думаю, что вам нужно создавать класс для этой цели. Вы можете просто определить операторы шаблона, не являющиеся членами, которые будут работать без прямого доступа к реализации std::array.

template <typename T, size_t N>
auto operator+(const array<T, N>& ob1, const array<T, N>& ob2)->array<T, N> {
    array<T, N> res;
    for (int i = 0; i < N; ++i)
        res[i] = ob1[i] + ob2[i];
    return res; 
}

И так далее для других арифметических операций.

person Александр Кушни&    schedule 12.05.2019
comment
или просто используйте std::valarray, новый класс создавать не нужно. - person phuclv; 12.05.2019