c ++ массив шаблонного абстрактного базового класса без нарушения правила строгого алиасинга - PullRequest
0 голосов
/ 30 ноября 2018

Каков наилучший способ создания массива объектов, полученных из базового класса абстрактного шаблона, без нарушения правила строгого наложения имен.Каждый производный объект будет определять аргументы шаблона базового класса по-разному, но только через постоянное значение enum.Вот пример

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 };

}

1 Ответ

0 голосов
/ 30 ноября 2018

Проблема в том, что class B : public A<int, BlaEnum::Bla2> и class C : public A<int, BlaEnum::Bla3> происходят из разных A, которые не совместимы друг с другом.Каждый из этих классов вызывает создание нового класса шаблона (ни один из которых не совместим с A<int>).

Для того, чтобы иметь действительную общую базу, вам необходим базовый класс, который не отличается ни одним из параметров шаблона(или это не шаблонный класс) из производных классов.
Изменение вашего примера, например:

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 };
}

Еще одно примечание: массивы в стиле C не являются хорошей практикой, вы должны предпочесть std::array (или std::vector) и умный указатель на необработанные указатели

...