Преобразование C ++ в тот же класс - PullRequest
0 голосов
/ 26 июня 2018

У меня есть пользовательская реализация для массивов с произвольными верхними и нижними границами.Теперь я хочу иметь возможность свободно преобразовывать массивы одного типа, если они имеют одинаковую длину.В коде это выглядит так:

template<typename T, int L, int H>
class Array{
    public:
        // stuff ...

        operator Array<T, int lb, int hb>& () {
            auto converted = Array<T, lb, hb>;
            converted.actualArray = actualArray;
            converted.offset = lb;
            return *converted;
        }
    private:
        T actualArray[H - L + 1];
        int offset = 0 - L;
}

Как видите, класс должен преобразовываться в себя.Как вы, вероятно, также можете видеть, я довольно нубирующий в C ++, так как моя ошибка выглядит синтаксической:

wrong number of template arguments (2, should be 3)
operator Array<T, int lb, int hb>& () {
                                ^

'<expression error>' does not name a type
operator Array<T, int lb, int hb>& () {
^

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

1 Ответ

0 голосов
/ 26 июня 2018

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

Даже если вы могли бы правильно настроить параметры шаблона, он все равноне работает, поскольку вы не можете назначить необработанный массив другому необработанному массиву.Вместо этого вам нужно скопировать элементы, например, с помощью std:copy() или std::copy_n().

. Попробуйте что-то более похожее на это:

#include <algorithm>

template<typename T, size_t L, size_t H>
class Array
{
public:
    static_assert(H >= L);
    static const size_t Low = L;
    static const size_t High = H;
    static const size_t Length = (H - L + 1);

    // stuff ...

    template<size_t Lb, size_t Hb>
    operator Array<T, Lb, Hb>() const
    {
        static_assert(Length == Array<T, Lb, Hb>::Length);
        Array<T, Lb, Hb> converted;
        std::copy_n(actualArray, Length, converted.actualArray);
        return converted;
    }

    // just to show that you don't need an offset member...

    T& operator[](size_t idx)
    {
        return actualArray[idx - L];
    }

    T operator[](size_t idx) const
    {
        return actualArray[idx - L];
    }

    template<typename, size_t, size_t>
    friend class Array;

private:
    T actualArray[Length];
};

Live Demo

Альтернативно, вы можете определить конструктор копирования, который принимает несколько типов Array одного размера массива, и тогда вам больше не нужен оператор преобразования:

#include <algorithm>

template<typename T, size_t L, size_t H>
class Array
{
public:
    static_assert(H >= L);
    static const size_t Low = L;
    static const size_t High = H;
    static const size_t Length = (H - L + 1);

    // stuff ...

    Array() = default;

    template<size_t Lb, size_t Hb>
    Array(const Array<T, Lb, Hb> &src)
    {
        static_assert(Length == Array<T, Lb, Hb>::Length);
        std::copy_n(src.actualArray, Length, actualArray);
    }

    // just to show that you don't need an offset member...

    T& operator[](size_t idx)
    {
        return actualArray[idx - L];
    }

    T operator[](size_t idx) const
    {
        return actualArray[idx - L];
    }

    template<typename, size_t, size_t>
    friend class Array;

private:
    T actualArray[Length];
};

Live Demo

...