【问题标题】:Operator overloading with class template parameter带有类模板参数的运算符重载
【发布时间】:2020-02-07 23:12:04
【问题描述】:

我正在研究一个高度模板化的数学向量类。它的维度和组件的类型都是这样模板化的。

#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&lt;T&gt;::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*' : no global operator found which take type 'Math::Vector' (或没有可接受的转换)”

#include "Vector.h"

#include <stdio.h>

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

我应该怎么做才能完成这项工作?

【问题讨论】:

  • 请提供与错误消息匹配的minimal reproducible example。您发布的代码中没有Math
  • 为了这个问题,您可以将Math::Vector 替换为std::vector 以纯粹测试您的模板化方式。
  • @bloody 这不是 std::vector。这是我自己实现的数学向量。
  • @SangWanJeon 虽然这对你提出的问题并不重要。虽然您编辑问题以包含代码是件好事,但您没有尊重一个好问题的要求之一:包含 minimal 代码。您包含的代码包含许多与此处无关的内容。
  • @KonradRudolph 我编辑了两次,第一次是包含代码,第二次是最小化它。我想你正在看第一个。很抱歉给您带来不便,但您可以重新加载问题吗?

标签: c++ templates operator-overloading


【解决方案1】:

你应该在 Vector 类中使用 operator* 的这个实现:

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;
}

此外,您应该修复 operator= 实现。您尝试更改 dimension 字段的值,但它是 const 并且您应该使用 operator= 来复制 std::array 字段。因此,您可以使用以下代码:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    相关资源
    最近更新 更多