3

I'm trying to design a hierarchy classes that extends the integers C types. What I'm trying to achieve is basically the following:

I have a basic class called Integer this class is an abstract class, the only thing I wish it would provide is basically the basic operations between integers, namely +,-,*,/,&,^,|,~,etc if I'm missing something, just the interface no implementation. Then I would subclass such class with StaticInteger and DynamicInteger the difference is that the StaticInteger uses templates to describes the size of the type at compile time, while DynamicInteger the size can be changed at run time.

Some use case would be the following for both classes:

StaticInteger<14> is1 = 3;
StaticInteger<32> is2 = 15;
StaticInteger<16> is3 = is1 + is2;

DynamicInteger id1;
id1.setWidth(14);
id1.setWidth(16);
id1 = is1;

Internally the data is represented by using arrays, so for example the resizing in the dynamic type would be achieved using new/delete operators;

Basically what puzzles me is how to properly design the interface of the base abstract class Integer. Let's say I would design straightly the class StaticInteger I woudl try to do something like:

template <int L>
class StaticInteger {
public:
  //bla bla
  template <int M>
  StaticInteger<L> operator+(StaticInteger<M> x);
private:
  //bla bla
};

The dynamic instead would be

class DynamicInteger {
 public:
   DynamicInteger operator+(DynamicInteger x);
 private:
};

but how would I specify the interface that would cover any possible interface of such operator? Between static and dynamic I think is clear that in general for a given operator the algorithm implementation could differ.

Just a further note, I do understand there's probably a philosophical problem behind what I'm trying to do, since an operator is actually a function in C++, and to be properly defined it requires all the types specified a priory, in the base class.

Update : Just an alternative design, I was thinking maybe I could abstract the concept of operations using a separate class (like a strategy pattern).

Separation of the data Integer from the operations

  • Your example usage of StaticInteger is problematic, as you are assigning 32 somethings into 16 slots. You may want only want implicit conversions that widen, and have explicit narrowing conversions – Caleth Oct 4 '16 at 11:45
  • There's no problem. I was trying to give an example of what I'm trying to achieve, the actual implementation, with corner case handling etc it's nothing that concerns me for now. – user8469759 Oct 4 '16 at 15:48
  • What benefits are you trying to achieve with this proposed system? – whatsisname Oct 4 '16 at 18:36
  • I'll speak broadly because I can't touch too many details. The main benefit would mainly be that that I could use the "Dynamic types" for optimization purpose (somehow I could dinamically size the bitwidth) while once I've found the configuration i want the static counterpart could be used for an actual implementation. Mostly related to numerical stuff (as you probably now fixed arithmetic is actually the base for the floating point arithmetic etc). – user8469759 Oct 4 '16 at 18:52
  • In general I think stuff like this, implemented in this way can have useful applications. – user8469759 Oct 4 '16 at 18:55
3

There would be an easy way out of this, that could avoid you defining all sorts of overloads for operator+ in DynamicInteger: just define a constructor based on a StaticInteger, and let the compiler try to organize implicit conversions:

class DynamicInteger {
 public:
    template <int M>
    DynamicInteger (StaticInteger<M> m ) {
           cout<<"construct Dynamic from "<< M<<endl;  // for demo purpose
    } 
    DynamicInteger operator+(DynamicInteger x) { ... }
 ...
};

Then you can write the following:

StaticInteger<16> a = 10, b=20; 
DynamicInteger x = a;         // coonvert a StaticInteger value to DynamicInteger
DynamicInteger z = x + b;     // mix StaticIntger in expressions to get them converted

Demo

Additional "philosophical" considerations (see discussion in the comments)

You don't need a common base class nor build a hierarchy. A proper definition of the operators, including conversion and eventually operators mixing types, is sufficient.

This doesn't prevent you from from using a common base class if you think it may help. You could for example decide to implement first a DynamicInteger , and then let the StaticInteger inherit from it (e.g.predefining the size at construction and raising an overflow instead of increasing dynamically the size). On the other hand, a pure template type would have the advantage of higher performance thanks to compile time optimizations and lighter memory management with fixed (templatized) size arrays.

Philosophically speaking, you don't need a hierarchy either: you just need to define the rules. Ok, you can add, multiply, divide integer, fractional , real and even complex numbers and mix them as suit; they have in common that they are all numbers. But on the other hand you can also add, multiply, divide vectors, which are not numbers but an abstract mathematical concept. You can also divide an apple pie by a number, despite the fact that they do not have a common ancestor.

Finally, let's have a look at the list<Integers>. First note that the standard C++ doesn't provide this kind of universality for the basic types : you'd have to choose a specific type at compilation time. If you don't want to make the decision, you could defer it to exectution, which means to create a more complex object, such as a union or a variant. For your generalized integer list, the situation is the same. So do you really need this kind of generalization ? If yes, you could indeed use a common base class but with the advantages and inconvenient that I already mentioned.

  • So I should not define any base class? But just two classes dinamic integer and static integer? What would be the hierarchy? – user8469759 Oct 3 '16 at 21:15
  • 3
    @user8469759 you don't have to define any hierarchy to work on these types. It's sufficient to define the conversion operations and/or the operators that allow to mix them. This doesn't prevent you from using some base class if you'd like to, but it's not an obligation. – Christophe Oct 3 '16 at 21:43
  • Note that you are defining (roughly) INT_MAX + 1 classes, many different StaticIntegers and one DynamicInteger. You will find that you will also need a conversion between two differently parameterised StaticIntegers – Caleth Oct 4 '16 at 11:42
  • I have a philosophical question, both static integer and dynamic integer are "algebraic models", they share the concept of "+,-,..." etc why don't express such common concept using a base class? – user8469759 Oct 4 '16 at 15:50
  • I'm just a little confused because in a large scale algorithm maybe I'd like to mix things like having a list<Integers> where both statics and dynamics variables are stored. The differentiation would restrict me a little bit on that, am I right? – user8469759 Oct 4 '16 at 16:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.