I'm implementing a Big Integer library where the user can choose between fixed precision or arbitrary precision integers. Since great part of the code is shared between the two entities I've decided to use the CRTP to implement the Integer operations just once.
In short there is a base class named Integer and two derived classes named IntegerFP (fixed precision) and IntegerAP (arbitrary precision).
Follows a skeleton of the implementation:
template <typename Derived>
class UInteger
{
public:
void +=(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 resize(int size) { m_data.resize(len); }
private:
std::vector<uint32_t> m_data;
};
The base class uses a couple of methods exposed by the derived classes to interact with implementation dependent aspects (ie like get_size/set_size).
My problem:
I want to implement a global binary operator+() that returns the result of the operation by value in the UInteger "generic" header file in this way:
template <typename Derived>
UInteger<Derived> operator+(const UInteger<Derived> &x0,
const UInteger<Derived> &x1)
{
Derived res = x0;
x0 += x1;
return x0;
}
The problem is that, since the result is returned by value, it is casted to the base class type loosing the implementation details (e.g. the m_data vector destructor is called). Obviously I do not get this problem if I define the function to return a type T by value:
template <typename Derived>
Derived operator+(const UInteger<Derived> &x0,
const UInteger<Derived> &x1)
{
Derived res = x0;
x0 += x1;
return x0;
}
But I don't like too much this approach.
Is there a better solution to this problem? Mainly from a design point of view. Maybe I should put such operators definitions directly in the Derived classes header file?
Somebody thinks that the CRTP is not very here and maybe is better to directly implement just one UInteger class in this way:
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
}
and if the bool "dynamic" value is false I never reallocate the vector so to obtain something similar to the UIntegerFP template class. Maybe, since the boolean is a template parameter I also abtain something like conditional code compilation ...
Suggestions of any type are very welcome,
Thanks, Davide
Aucun commentaire:
Enregistrer un commentaire