Перегрузка оператора параметром шаблона класса - PullRequest
0 голосов
/ 10 октября 2019

Я работаю над сильно математическим классом Vector. Его размер и тип компонентов настроены следующим образом.

#pragma once

#include <array>
#include <type_traits>
#include <cassert>

namespace Math
{   
    template <size_t D, typename T = double>
    class Vector
    {
        //
        // Template Assertions
        //
        static_assert(D > 0, "Dimension of an Vector must be bigger than 0");
        static_assert(std::is_arithmetic<T>::value, "Component Type of Vector must be Arithmetic");

        //
        // Template Typedefs
        //
        template <typename... > struct typelist;

        //
        // Private Variables
        //

        std::array<T, D> _components;

        Vector(std::array<T, D> components) : _components(components), dimension(D)
        {
            static_assert(components.size() == D, "Component Count must match Dimension");
        }

    public:
        //
        // Public Variables
        //

        const size_t dimension;

        //
        // Constructors
        //

        template <typename ...Args, typename = std::enable_if_t<!std::is_same<typelist<Vector>, typelist<std::decay_t<Args>...>>::value>>
        Vector(Args&&... args) : _components{ T(args)... }, dimension(D)
        {
            static_assert(sizeof...(Args) == D, "Component Count must match Dimension");
        }

        Vector(const Vector &t) : _components(t._components), dimension(t.dimension)
        {
            assert(t.dimension == D);
        }

        //
        // Operators
        //

        Vector& operator=(const Vector& other)
        {
            if (this != &other) {
                _components(other._components);
                dimension = other._components.size();
            }
            return *this;
        }

        T& operator[](const size_t index)
        {
            return _components[index];
        }

        const T& operator[](const size_t index) const
        {
            return _components[index];
        }

    };

    //
    // Operators
    //
    typedef Vector<2> Vector2;
    typedef Vector<3> Vector3;

    template<size_t D, typename T, typename K, std::enable_if_t<std::is_arithmetic<K>::value>>
    Vector<D, T> operator*(const K& lhs, Vector<D, T>& rhs) {
        Vector<D, T> vec = Vector<D, T>(rhs);
        for (size_t i = 0; i < vec.dimension; ++i)
        {
            vec[i] = vec[i] * lhs;
        }

        return vec;
    }
}

Я хочу, чтобы каждый арифметический тип (Arithmetic_Type с std::is_arithmetic<T>::value == true) имел operator* для работы с моим пользовательским классом. Поэтому я попробовал эту operator* подпись вне класса.

template<size_t D, typename T, typename K, std::enable_if_t<std::is_arithmetic<K>::value>>
Vector<D, T> operator*(const K& lhs, Vector<D, T>& rhs) {
    Vector<D, T> vec = Vector<D, T>(rhs);
    for (size_t i = 0; i < vec.dimension; ++i)
    {
        vec[i] = vec[i] * lhs;
    }

    return vec;
}

Он хорошо компилируется, но если я пытаюсь использовать их таким образом, он не находит operator*.
(Так как я использую Visual Studio, код ошибки - C2677, "двоичный"'operator *': не найден глобальный оператор, который принимает тип 'Math :: Vector <2U, double>' (или нет приемлемого преобразования) "

#include "Vector.h"

#include <stdio.h>

int main()
{
    Math::Vector<2> v1 = Math::Vector<2>(2, 3);
    v1 = 2 * v1;
    return 0;
}

Что я должен сделать, чтобы эта работа работала?

1 Ответ

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

Вы должны использовать эту реализацию оператора * внутри класса Vector:

template<typename K>
friend std::enable_if_t<std::is_arithmetic<K>::value, Vector> operator*(K lhs, Vector& rhs) {
    Vector vec(rhs);
    for (size_t i = 0; i < vec.dimension; ++i)
    {
        vec[i] = vec[i] * lhs;
    }
    return vec;
}

Также вы должны исправить оператор = реализацию. Вы пытаетесь изменить значение поля dimension , но оно является постоянным, и вы должны использовать operator =, чтобы скопировать поле std :: array. Итак, вы можете использовать этот код:

Vector& operator=(const Vector& other)
{
    if (this != &other) {
        _components = other._components;
    }
    return *this;
}
...