【问题标题】:Operator overloading with integer template parameter specialization具有整数模板参数特化的运算符重载
【发布时间】:2018-05-24 08:20:31
【问题描述】:

我有一个向量类定义如下:

template <unsigned int SIZE>
class Vector : public Stringable
{
    private:

        float mData [SIZE];

    public:
        Vector ();

        ...
};

我还在这个(数学)向量上声明了一些运算符(在 Vector 类之外):

template <unsigned int SIZE>
Vector<SIZE> operator+ (const Vector<SIZE>& vec, float c);

template<>
Vector<3> operator+ (const Vector<3>& vec, float c);

template<>
Vector<4> operator+ (const Vector<4>& vec, float c);

template <unsigned int SIZE>
Vector<SIZE> operator+ (const Vector<SIZE>& vec1, const Vector<SIZE>& vec2);

template <>
Vector<3> operator+ (const Vector<3>& vec1, const Vector<3>& vec2);

template <>
Vector<4> operator+ (const Vector<4>& vec1, const Vector<4>& vec2);

这是它们的实现方式:

template <unsigned int SIZE>
Vector<SIZE> operator+(const Vector<SIZE>& vec1, const Vector<SIZE>& vec2)
{
    Vector<SIZE> result = Vector<SIZE>(vec1);

    int i = 0;
    for (i = 0; (i + 4) < SIZE; i += 4)
    {
        __m128 lhs = _mm_set_ps(vec1[i], vec1[i+1], vec1[i+2], vec1[i+3]);
        __m128 rhs = _mm_set_ps(vec2[i], vec2[i+1], vec2[i+2], vec2[i+3]);
        _mm_add_ps(lhs, rhs);
        _mm_store_ps(result.getRawData(), lhs);
    }

    for (; i < SIZE; i++)
    {
        result[i] = vec1[i] - vec2[i];
    }

    return result;
}

template<>
Vector<3> operator+<3>(const Vector<3>& vec1, const Vector<3>& vec2)
{
    Vector<3> result = Vector<3>(vec1);
    float tmpBuffer [4];

    __m128 lhs = _mm_set_ps(vec1[0], vec1[1], vec1[2], 0);
    __m128 rhs = _mm_set_ps(vec2[0], vec2[1], vec2[2], 0);
    _mm_add_ps(lhs, rhs);
    _mm_store_ps(tmpBuffer, lhs);
    mempcpy(result.getRawData(), tmpBuffer, 3 * sizeof(float));

    return result;
}

template<>
Vector<4> operator+<4>(const Vector<4>& vec1, const Vector<4>& vec2)
{
    Vector<4> result = Vector<4>(vec1);

    __m128 lhs = _mm_set_ps(vec1[0], vec1[1], vec1[2], vec1[3]);
    __m128 rhs = _mm_set_ps(vec2[0], vec2[1], vec2[2], vec1[3]);
    _mm_add_ps(lhs, rhs);
    _mm_store_ps(result.getRawData(), lhs);

    return result;
}

template <unsigned int SIZE>
Vector<SIZE> operator+(const Vector<SIZE>& vec, float c)
{
    Vector<SIZE> result = Vector<SIZE>(vec);

    int i = 0;
    for (i = 0; (i + 4) < SIZE; i += 4)
    {
        __m128 lhs = _mm_set_ps(vec[i], vec[i+1], vec[i+2], vec[i+3]);
        __m128 rhs = _mm_set1_ps(c);
        _mm_add_ps(lhs, rhs);
        _mm_store_ps(result.getRawData(), lhs);
    }

    for (; i < SIZE; i++)
    {
        result[i] = vec[i] + c;
    }

    return result;
}

template <>
Vector<3> operator+<3>(const Vector<3>& vec, float c)
{
    Vector<3> result = Vector<3>(vec);
    float tmpBuffer [4];

    __m128 lhs = _mm_set_ps(vec[0], vec[1], vec[2], 0);
    __m128 rhs = _mm_set1_ps(c);
    _mm_add_ps(lhs, rhs);
    _mm_store_ps(tmpBuffer, lhs);
    mempcpy(result.getRawData(), tmpBuffer, 3 * sizeof(float));

    return result;
}

template <>
Vector<4> operator+<4>(const Vector<4>& vec, float c)
{
    Vector<4> result = Vector<4>(vec);

    __m128 lhs = _mm_set_ps(vec[0], vec[1], vec[2], 0);
    __m128 rhs = _mm_set1_ps(c);
    _mm_add_ps(lhs, rhs);
    _mm_store_ps(result.getRawData(), lhs);

    return result;
}

以上所有代码都在一个文件中:“Vector.cpp”

我目前正在使用英特尔的 SSE Intrinsics 从“正常”向量操作转移到 SIMD 操作。

由于大小为 3 和 4 的向量在我的应用程序中很常见,我想专门针对这些向量使用模板运算符,以便更好地使用 XMM 寄存器。 (如您所见,SIMD 循环不会用于任何大小

不幸的是,我不知道如何真正做到这一点,我真的不知道我需要什么声明/定义,模板参数需要是什么,...

编辑:现在,我收到“多个定义”链接器错误,我使用的是 clang++ 5.0

其中大约有 50 个错误(很多,50 个只是一个猜测时间),所有的专业似乎都存在......

CMakeFiles/Space.elf.dir/src/Entities/Entity.cpp.o: In function `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, float)':
/home/.../CLionProjects/Space/src/Maths/Vector.cpp:427: multiple definition of `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, float)'
CMakeFiles/Space.elf.dir/src/main.cpp.o:/home/.../CLionProjects/Space/src/Maths/Vector.cpp:427: first defined here
CMakeFiles/Space.elf.dir/src/Entities/Entity.cpp.o: In function `Maths::Vector<4u> Maths::operator+<4u>(Maths::Vector<4u> const&, Maths::Vector<4u> const&)':
/home/.../CLionProjects/Space/src/Maths/Vector.cpp:392: multiple definition of `Maths::Vector<4u> Maths::operator+<4u>(Maths::Vector<4u> const&, Maths::Vector<4u> const&)'
CMakeFiles/Space.elf.dir/src/main.cpp.o:/home/.../CLionProjects/Space/src/Maths/Vector.cpp:392: first defined here
/home/.../CLionProjects/Space/src/Maths/Vector.cpp:377: multiple definition of `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, Maths::Vector<3u> const&)'
CMakeFiles/Space.elf.dir/src/main.cpp.o:/home/.../CLionProjects/Space/src/Maths/Vector.cpp:377: first defined here
CMakeFiles/Space.elf.dir/src/Entities/EntityManager.cpp.o: In function `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, float)':

我已经删除了部分路径,但你明白了这个想法

【问题讨论】:

  • 有头文件Vector.h吗?我认为所有模板定义都必须在标题中。

标签: c++ templates integer operator-overloading


【解决方案1】:

好的,我解决了我的问题,方法如下。 我像通常对任何其他类一样将定义和声明分开。 然后在我的实现文件 (.cpp) 的底部,我不仅显式实例化了我的类,还显式实例化了我的所有运算符。

(不幸的是,加载/卸载的数量使 SIMD 指令过时,因为它产生的开销比它摆脱的要多。专门化完整类可能是这里的解决方案,但那是另一次了)

【讨论】:

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