3

我想构建一个节省空间的模块化算术类。这个想法是模数 M 是一个在实例化期间固定的不可变属性,因此如果我们有一个具有相同 M 值的大型数组(std::vector 或其他容器),则 M 只需要存储一次。

如果 M 可以在编译时固定,这可以使用模板来完成:

template <typename num, num M> class Mod_template
{
    private:
        num V;
    public:
        Mod_template(num v=0)
        {
            if (M == 0)
                V = v;
            else
            {
                V = v % M;
                if (V < 0)
                    V += M;
            }
        }
        // ...
};

Mod_template<int, 5> m1(2); // 2 mod 5

但是,在我的应用程序中,我们应该能够表达 M 运行时。我所拥有的看起来像这样:

template <typename num> class Mod
{
    private:
        const num M;
        num V;
    public:
        Mod(num m, num v=0): M(abs(m))
        {
            if (M == 0)
                V = v;
            else
            {
                V = v % M;
                if (V < 0)
                    V += M;
            }
        }
        // ...
};

Mod<int> m2(5, 2); // 2 mod 5
Mod<int> m3(3);    // 0 mod 3

这可行,但是 mod M 值的大向量使用它需要的空间的 2 倍。

我认为潜在的概念问题是不同模数的 Mod 在语法上属于相同类型,即使它们“应该”是不同的类型。例如,像这样的语句

m2 = m3;

应该“自然”引发运行时错误(在我的版本中,它“手动”这样做:检查内置于复制构造函数以及我实现的每个二元运算符中)。

那么,有没有办法实现某种动态类型,以便 Mod 对象的类型记住模数?我真的很感激任何想法如何解决这个问题。

这对我来说是一个反复出现的问题,涉及各种数学结构(例如,在同一集合上存储许多排列、同一组的元素等)

编辑:据我所知,

  • 模板是由类或文字参数化的类型。

  • 我想要什么:由 const 对象参数化的类型(const num在这种情况下,const Group&const Group *const用于组等)。

这可能吗?

4

1 回答 1

1

如果班级需要知道M在没有任何外部帮助的情况下应该做什么,那么在零存储空间中很难做到这一点。您可以做的最好的事情可能是存储一个指向 shared 的指针M,这可能会更好一些,具体取决于它的大小num。但它不如免费。

M如果是所有需要它的函数的传入值,则设计起来会更容易。然后你可以做一些事情,比如创建一个共享相同的对象池M(有很多简单的方法来设计它;例如map<num, vector<num> >)并且只为池存储M一次。调用者需要知道Mod对象来自哪个池,但这可能是它知道的东西。

很难孤立地完美回答这个问题......了解更多关于调用代码的信息肯定会帮助您获得更好的答案。

于 2014-06-23T17:30:01.810 回答