C ++ BigIntegers和奇怪的重复模板模式问题

时间:2015-11-10 19:51:53

标签: c++ templates design-patterns biginteger crtp

我正在实现一个Big Integer库,用户可以在固定精度或任意精度整数之间进行选择。由于很大一部分代码是在两个实体之间共享的,所以我决定使用CRTP只执行一次Integer操作。

简而言之,有一个名为UInteger的基类和两个名为UIntegerFP(固定精度)和UIntegerAP(任意精度)的派生类。

遵循实施的框架:

template <typename Derived>
class UInteger
{
public:
    UInteger<Derived> &operator +=(const UInteger<Derived> &rhs);
    ...
};

template <int blocks>
class UIntegerFP : public UInteger<UIntegerFP>
{
public:
    int get_size() { return m_len; }
    void set_size(int size) { m_len = len; }
private:
    std::array<uint32_t, blocks>    m_data;
    int                             m_len;  
};

class UIntegerAP : public UInteger<UIntegerAP>
{
public:
    int get_size() { return m_data.size(); }
    void set_size(int size) { m_data.resize(len); } 
private:
    std::vector<uint32_t>           m_data;
};

基类使用派生类公开的几个方法与依赖于实现的方面进行交互(例如get_size / set_size)。

我的问题:

我想实现一个全局二元运算符+(),它以这种方式在UInteger“generic”头文件中按值返回操作的结果:

template <typename Derived>
UInteger<Derived> operator+(const UInteger<Derived> &x0, 
                            const UInteger<Derived> &x1)
{
    Derived res = static_cast<Derived>(x0);
    x0 += x1;
    return x0;
}

问题在于,由于结果是按值返回的,因此会将其转换为基类类型,从而忽略实现细节(例如,调用m_data向量析构函数)。 显然,如果我定义函数以按值返回Derived类型,我就不会遇到这个问题:

template <typename Derived>
Derived operator+(const UInteger<Derived> &x0, 
                  const UInteger<Derived> &x1)
{
    Derived res = static_cast<Derived>(x0);
    x0 += x1;
    return x0;
}

但我不太喜欢这种方法,特别是从设计的角度来看。

这种问题有更好的解决方案吗?也许我应该直接为派生类定义这样的运算符? 是否有人认为CRTP在这里不太合适,也许以这种方式直接实现一个UInteger类更好:

template <bool dynamic = true> 
class UInteger
{
...
private:
    std::array<uint32_t> m_data;
    int m_len; <- how much of m_data array is actually in use
}

如果bool“dynamic”值为false,我永远不会重新分配向量,获取类似于UIntegerFP模板类的东西。也许(如果编译器足够智能),因为布尔值是一个const模板参数,我还可以获得类似条件代码编译的东西吗?!

非常欢迎任何类型的建议,

谢谢, 的Davide

2 个答案:

答案 0 :(得分:0)

我不太明白为什么要以这种方式使用CRTP。

当仅通过派生方法完成内存管理时,CRTP是实现/Users/balterma/Library/Enthought/Canopy_64bit/User/lib/python2.7/sitepackages/matplotlib/colors.py:584: RuntimeWarning: invalid value encountered in less cbook._putmask(xa, xa < 0.0, -1) =操作的实际细节的自然方式。这种设计清楚地将算术和内存管理这两项任务分为不同的类。然后,+=(二进制)运算符最好作为独立的函数模板实现。

这样的事情:

+

答案 1 :(得分:0)

operator+实现中,实际上,您将函数返回类型设置为:

  • UIntegerAP如果其中一个模板类型为UIntegerAP
  • Ulhs,否则(此处我认为您打算UIntegerFP)。

是吗?

现在......如果UIntegerAP也是模板怎么办?例如,定义如下:

template <typename block_type>
class UIntegerAP
{
   ....
private:    
    std::vector<block_type> m_data;
}

我不能再在UIntegerAP声明中使用operator+类型了。