Конструктор пакета параметров скрывает пользовательское преобразование в шаблоне класса - PullRequest
1 голос
/ 08 февраля 2020

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

template <unsigned int N, typename T>
class Vec
{
public:

    T m_components[N];

    Vec()
        : m_components{}
    { }

    template<typename ...Args>
    explicit Vec(Args... args)
        : m_components{args...}
    { }

    // ...
}

Я также добавил пользовательское преобразование для преобразования между классами, используя этот шаблон:

    // ...

    template <unsigned int _N, typename _T>
    explicit operator Vec<_N, _T> () const
    {
        Vec<_N, _T> vec;
        for(unsigned int i = 0; i < N && i < _N; ++i)
            vec.m_components[i] = static_cast<_T>(m_components[i]);
        return vec;
    }

    // ...

Однако, когда я вызываю пользовательское преобразование, я написал так:

Vec<2, int> a(2, 8);
Vec<4, double> b;
b = (Vec<4, double>)a;

Строка, в которой используется приведение в стиле C, вызывает следующее ошибка:

C2440: 'initializing': cannot convert from 'Vec<2, int>' to 'T' // points to the expansion of the parameter pack: m_components{args...}

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

1 Ответ

1 голос
/ 08 февраля 2020

Добавьте этот конструктор:

    // ...

    template <unsigned int _N, typename _T>
    explicit Vec(const Vec<_N, _T>& other)
    {
        for(unsigned int i = 0; i < N && i < _N; ++i)
            m_components[i] = static_cast<_T>(other.m_components[i]);
    }

    // ...

Как я понимаю, и я могу ошибаться (кто-то с большим опытом может объяснить лучше), компилятор не знает, как изменить текущий экземпляр вашего Шаблон класса для того, чтобы быть назначенным с другим.

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

...