Хобрук: Ваш путь к мастерству в программировании

Дружественные операторы шаблона С++ против дополнительного аргумента шаблона

Я создал класс Vector, который принимает количество элементов и тип элемента в качестве аргументов шаблона.

template<int n, class T>
class Vector
{
    public:
        T data[n];

        Vector()
        : data{}
        {
        }

        Vector(T const value)
        {
            std::fill_n(data, n, value);
        }

        template<class ...U, typename std::enable_if<sizeof...(U) == n, int>::type = 0>
        Vector(U &&...u)
        : data{std::forward<U>(u)...}
        {
        }

        T& operator[](int const index)
        {
            return data[index];
        }

        template<class U>
        operator Vector<n, U>()
        {
            Vector<n, U> out;

            std::copy_n(data, n, out.data);

            return out;
        } 
};

Я хочу иметь операторы для класса, но для того, чтобы они могли выполнять преобразования между векторами с различными типами элементов, они должны быть дружественными функциями, объявленными и определенными внутри тела класса. Но я также хочу иметь 3 специализированных класса-шаблона для Vector 2, 3 и 4. Так как я не хочу писать все операторы 4 раза, по одному разу внутри каждого тела класса. Могу ли я просто использовать этот оператор с дополнительным аргументом шаблона для типа элемента правого вектора?

template<int n, class T, class U>
inline Vector<n, T>& operator+=(Vector<n, T> &lhs, Vector<n, U> const &rhs)
{
    for(int i = 0; i < n; ++i)
    {
        lhs.data[i] += rhs.data[i];
    }

    return lhs;
}

Вероятно, есть причина, по которой люди используют операторы друзей внутри класса вместо того, чтобы делать это таким образом, но пока все выглядит нормально, я что-то упустил?


Ответы:


1

Здесь нет ничего, кроме суммы частей. «friend» используется для предоставления доступа к непубличным членам, которые операторы могут захотеть использовать, а размещение определения внутри класса экономит ввод (и неявно делает их встроенными, избегая проблем с одним правилом определения). Если вы собираете класс, вы можете начать вводить определение оператора «друг...», даже не задумываясь о том, должен ли он быть другом. Некоторым людям также может нравиться, когда операторы перечислены внутри класса — так легче убедиться, что они видны, когда кто-то просматривает класс, чтобы увидеть, какие функции доступны, — но программисты обычно привыкают искать операторы после класса в любом случае. ....

Если ваш код работает, все хорошо.

04.01.2014
  • «друг» делает больше, чем это. Мой вопрос похож на stackoverflow.com/questions/8890051/ . Операторная функция должна иметь возможность складывать вместе вектор чисел с плавающей запятой и вектор целых чисел. Но вывод аргумента шаблона происходит до неявного преобразования типов. Вместо того, чтобы использовать решение этого вопроса, я создал этот обходной путь. Мне интересно, вызовет ли мой обходной путь какие-либо проблемы, которых не возникло бы, если бы я использовал решение из этого вопроса. 04.01.2014
  • Этот ответ не иллюстрирует потребность в друге, о котором вы говорите - например, с общедоступным элементом value и шаблоном с двумя параметрами, охватывающим общий случай добавления, следующий код работает просто отлично: ideone.com/0hMp83 - это очевидный способ сделать это, и действительно - разве это не то, о чем вы спрашиваете в своем вопросе? - Я бы не назвал это обходным путем. 04.01.2014
  • Кроме того, в этом ответе есть шаблон с template <class U> foo(const foo<U>& that) : _value(that.getval()) {} - он вызывает болезненную неявную конструкцию дополнительного вектора до того, как сработает оператор +. Вам лучше использовать код в своем ответе. 04.01.2014
  • Новые материалы

    Как ИИ меняет сельское хозяйство
    Прочтите Статью Кэтлин Уолч в Forbes о том, как ИИ меняет сельское хозяйство . Сельское хозяйство и земледелие - одна из древнейших и важнейших профессий в мире. Человечество прошло долгий..

    Slack: проектирование современных интерфейсов человека и ИИ
    Когда Стюарт Баттерфилд выделил Slack из быстро исчезающей онлайн-игры Tiny Speck, его перспективы были в лучшем случае неопределенными. Существовал очевидный спрос на средства связи на рабочем..

    HTTP1.1 против HTTP2
    Http расшифровывается как HyperText Transfer Protocol, это в основном метод, который компьютеры и серверы используют для запроса и отправки информации. HTTP1.1 - это более старая версия Http, а..

    Радость вырезания
    Радость фрагментов По какой-то причине, когда я начал программировать в колледже, я активно сопротивлялся целому ряду земных благ, которые сделали бы мою жизнь чуточку удобнее. Я в основном..

    Создайте стройный слайдер с нуля без каких-либо внешних инструментов
    Слишком долго я полагался на сторонние плагины и инструменты для простых слайдеров. Пока в один прекрасный день в моей крошечной голове не загорелась лампочка, которую я могу сделать..

    Буферы протоколов, часть 01: соглашения об именах и файловая организация
    Если вам нравится читать статьи на Medium и вы заинтересованы в том, чтобы стать участником, я буду рад поделиться с вами своей реферальной ссылкой!

    Наши партнеры
    Globex SCI — уникальная система, которая хранит и позволяет использовать большие базы данных, опубликованные в блокчейне. Используя алгоритмы глубокого обучения и ИИ, мы можем прогнозировать..