鱼C论坛

 找回密码
 立即注册
查看: 678|回复: 2

[已解决]C++ 模板类特化中的变量问题

[复制链接]
发表于 2023-10-15 20:12:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我有这一段代码:
#include <array>
template <unsigned short dimensions>
class Vector
{
        public:
                static const unsigned short dimension = dimensions;
                std::array<double, dimensions> values;
                Vector() = default;
                Vector(const Vector &) = default;
                Vector(Vector &&) = default;
                Vector(std::array<double, dimensions> values)
                {
                        this->values = values;
                };
                Vector<dimensions> & operator=(const Vector<dimensions> &) = default;
                Vector<dimensions> operator+(const Vector<dimensions> &other) const
                {
                        Vector<dimensions> result;
                        for (unsigned short index = 0; index < dimensions; index++)
                        {
                                result.values[index] = this->values[index] + other.values[index];
                        };
                        return result;
                };
                Vector<dimensions> operator+(const double other) const
                {
                        Vector<dimensions> result;
                        for (unsigned short index = 0; index < dimensions; index++)
                        {
                                result.values[index] = this->values[index] + other;
                        };
                        return result;
                };
                Vector<dimensions> operator-() const
                {
                        Vector<dimensions> result;
                        for (unsigned short index = 0; index < dimensions; index++)
                        {
                                result.values[index] = -this->values[index];
                        };
                        return result;
                };
                Vector<dimensions> operator-(const Vector<dimensions> &other) const
                {
                        return (*this) + -other;
                };
                Vector<dimensions> operator-(const double other) const
                {
                        return *this + -other;
                };
                Vector<dimensions> operator*(const double other) const
                {
                        Vector<dimensions> result;
                        for (unsigned short index = 0; index < dimensions; index++)
                        {
                                result.values[index] = this->values[index] * other;
                        };
                        return result;
                };
                Vector<dimensions> operator/(const double other) const
                {
                        return *this * (1.0 / other);
                };
                double dot(const Vector<dimensions> &other) const
                {
                        double result = 0;
                        for (unsigned short index = 0; index < dimensions; index++)
                        {
                                result += this->values[index] * other.values[index];
                        };
                        return result;
                };
                double length() const
                {
                        return sqrt(this->dot(*this));
                };
                Vector<dimensions> length(const int scale) const
                {
                        return *this / (this->length() / scale);
                };
                double angle(const Vector<dimensions> &other) const
                {
                        return acos(this->dot(other) / (this->length() * other.length()));
                };
};

template <>
class Vector<3>
{
        public:
                Vector<3> operator*(const Vector<3> &other) const
                {
                        Vector<3> result;
                        for (unsigned short index = 0; index < 3; index++)
                        {
                                result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
                        };
                        return result;
                };
};
我对这个 Vector 进行特化,使其能够完成仅提供三维支持的叉乘,但是编译器报错说在特化中 'const class Vector<3>' has no member named 'values' ,难道特化不保有模板的函数和变量吗?如果不保有,那么怎么修改才能做到减少代码冗余;如果保有,那么这里为什么会报错,又怎么解决?
最佳答案
2023-10-15 20:12:55
在C++中,模板特化并不保留原模板的成员函数和变量。当你为模板类进行特化时,你实际上是在为特定的模板参数创建一个全新的类定义。这就是为什么在你的特化版本的 Vector<3> 中,编译器无法找到 values 成员的原因。

如果你希望在特化版本中保留一些通用的成员和函数,你可以考虑使用模板类的继承。例如,你可以创建一个基础的 VectorBase 类,然后让 Vector 继承自 VectorBase。这样,你就可以在 VectorBase 中定义通用的成员和函数,然后在 Vector 的特化版本中添加或覆盖特定的成员和函数。

以下是一个简单的示例:
template <unsigned short dimensions>
class VectorBase {
public:
    static const unsigned short dimension = dimensions;
    std::array<double, dimensions> values;
    // ... 其他通用的成员和函数 ...
};

template <unsigned short dimensions>
class Vector : public VectorBase<dimensions> {
    // ... 特定的成员和函数 ...
};

template <>
class Vector<3> : public VectorBase<3> {
public:
    Vector<3> operator*(const Vector<3> &other) const {
        Vector<3> result;
        for (unsigned short index = 0; index < 3; index++) {
            result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
        };
        return result;
    };
};

这样,Vector<3> 就可以访问 VectorBase<3> 中定义的 values 成员了。同时,你也可以在 Vector<3> 中添加或覆盖特定的成员和函数,以实现三维向量的特殊操作。
请注意,本回答来自GPT-4
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-10-15 20:12:55 | 显示全部楼层    本楼为最佳答案   
在C++中,模板特化并不保留原模板的成员函数和变量。当你为模板类进行特化时,你实际上是在为特定的模板参数创建一个全新的类定义。这就是为什么在你的特化版本的 Vector<3> 中,编译器无法找到 values 成员的原因。

如果你希望在特化版本中保留一些通用的成员和函数,你可以考虑使用模板类的继承。例如,你可以创建一个基础的 VectorBase 类,然后让 Vector 继承自 VectorBase。这样,你就可以在 VectorBase 中定义通用的成员和函数,然后在 Vector 的特化版本中添加或覆盖特定的成员和函数。

以下是一个简单的示例:
template <unsigned short dimensions>
class VectorBase {
public:
    static const unsigned short dimension = dimensions;
    std::array<double, dimensions> values;
    // ... 其他通用的成员和函数 ...
};

template <unsigned short dimensions>
class Vector : public VectorBase<dimensions> {
    // ... 特定的成员和函数 ...
};

template <>
class Vector<3> : public VectorBase<3> {
public:
    Vector<3> operator*(const Vector<3> &other) const {
        Vector<3> result;
        for (unsigned short index = 0; index < 3; index++) {
            result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
        };
        return result;
    };
};

这样,Vector<3> 就可以访问 VectorBase<3> 中定义的 values 成员了。同时,你也可以在 Vector<3> 中添加或覆盖特定的成员和函数,以实现三维向量的特殊操作。
请注意,本回答来自GPT-4
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-10-15 20:13:44 | 显示全部楼层
在模板类特化中,只有特化的部分会被编译器处理,其他部分将被忽略。因此,在 Vector<3> 的特化中,只有特化的部分会被编译器处理,而原始模板中的成员变量 values 并不会被保留。

要解决这个问题,可以使用继承来避免代码冗余。首先,将原始模板类中的所有成员函数和变量都放在一个基类中,然后在特化中继承这个基类并添加新的成员函数和变量。这样,特化中就可以使用基类中的成员变量 values 了。

以下是修改后的代码:
#include <array>
#include <cmath>

template <unsigned short dimensions>
class VectorBase
{
public:
    static const unsigned short dimension = dimensions;
    std::array<double, dimensions> values;
    VectorBase() = default;
    VectorBase(const VectorBase &) = default;
    VectorBase(VectorBase &&) = default;
    VectorBase(std::array<double, dimensions> values)
    {
        this->values = values;
    };
    VectorBase<dimensions> &operator=(const VectorBase<dimensions> &) = default;
    VectorBase<dimensions> operator+(const VectorBase<dimensions> &other) const
    {
        VectorBase<dimensions> result;
        for (unsigned short index = 0; index < dimensions; index++)
        {
            result.values[index] = this->values[index] + other.values[index];
        };
        return result;
    };
    VectorBase<dimensions> operator+(const double other) const
    {
        VectorBase<dimensions> result;
        for (unsigned short index = 0; index < dimensions; index++)
        {
            result.values[index] = this->values[index] + other;
        };
        return result;
    };
    VectorBase<dimensions> operator-() const
    {
        VectorBase<dimensions> result;
        for (unsigned short index = 0; index < dimensions; index++)
        {
            result.values[index] = -this->values[index];
        };
        return result;
    };
    VectorBase<dimensions> operator-(const VectorBase<dimensions> &other) const
    {
        return (*this) + -other;
    };
    VectorBase<dimensions> operator-(const double other) const
    {
        return *this + -other;
    };
    VectorBase<dimensions> operator*(const double other) const
    {
        VectorBase<dimensions> result;
        for (unsigned short index = 0; index < dimensions; index++)
        {
            result.values[index] = this->values[index] * other;
        };
        return result;
    };
    VectorBase<dimensions> operator/(const double other) const
    {
        return *this * (1.0 / other);
    };
    double dot(const VectorBase<dimensions> &other) const
    {
        double result = 0;
        for (unsigned short index = 0; index < dimensions; index++)
        {
            result += this->values[index] * other.values[index];
        };
        return result;
    };
    double length() const
    {
        return std::sqrt(this->dot(*this));
    };
    VectorBase<dimensions> length(const int scale) const
    {
        return *this / (this->length() / scale);
    };
    double angle(const VectorBase<dimensions> &other) const
    {
        return std::acos(this->dot(other) / (this->length() * other.length()));
    };
};

template <unsigned short dimensions>
class Vector : public VectorBase<dimensions>
{
public:
    using VectorBase<dimensions>::VectorBase;
};

template <>
class Vector<3> : public VectorBase<3>
{
public:
    Vector<3> operator*(const Vector<3> &other) const
    {
        Vector<3> result;
        for (unsigned short index = 0; index < 3; index++)
        {
            result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
        };
        return result;
    };
};

在这个修改后的代码中,VectorBase 类包含了原始模板中的所有成员函数和变量,Vector 类和 Vector<3> 类继承了 VectorBase 类并添加了新的成员函数。这样,Vector<3> 就可以使用基类中的成员变量 values 了。

希望这个解决方案能够帮到你!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-23 21:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表