0

What is the best way to create an array of objects derived from an abstract template base class without violating the strict-aliasing rule. Each derived object will define the template arguments of the base class differently but only through the constant enum value. Here is an example

enum  BlaEnum
{
  Bla1,
  Bla2,
  Bla3
};

template <class T, BlaEnum bla = Bla1>
class A
{
public:
   virtual void Foo() = 0;
   T att;
   BlaEnum bll;
};

class B : public A<int, BlaEnum::Bla2>
{
public:
   void Foo() override;
};

 class C : public A<int, BlaEnum::Bla3>
{
public:
   void Foo() override;
};

int main(void)
{

  B b;
  C c;

  //violates strict-aliasing rule
  A<int>* BaseArr[2] = { (A<int>*)&b,(A<int>*)&c };

}
curiousguy
  • 8,038
  • 2
  • 40
  • 58
Hadi Jaber
  • 145
  • 3
  • 10
  • 1
    instantiations with different actual type parameters are different classes, unrelated to each other (by inheritance or any other relation), notwithstanding the common template name. – davidbak Nov 30 '18 at 19:28

1 Answers1

1

The problem here is that class B : public A<int, BlaEnum::Bla2> and class C : public A<int, BlaEnum::Bla3> derive from different A that are not compatible with each other. Each of those classes causes the instantiation of a new template class (neither of which are compatible with A<int>).

In order to have valid common base you require a base class that does not differ in any template parameters (or is a non-template class) from the derived classes.
Modifying your example e.g.:

template <class T>
class Base 
{
public:
    virtual void Foo() = 0;
};

template <class T, BlaEnum bla = Bla1>
class A : public Base<T>
{
public:
   T att;
   BlaEnum bll;
};
// B and C are unchanged
int main()
{
  B b;
  C c;
  // Array of pointers to common base class
  Base<int>* BaseArr[2] = { &b,&c };
}

One more note: C-style arrays are not a good practice, you should prefer std::array(or std::vector) and smart pointer over raw pointers

UnholySheep
  • 3,967
  • 4
  • 19
  • 24