vendredi 28 août 2015

Call to derived class function in vector populated with variadic initializer list doesn’t behave polymorphically

I am using an initializer list to declare an arbitrary number of item pairs at compile time, each consisting of a key and a real type as the value. There are two derived real types in the model code: MyA and MyB, both of which derive from My. The vector gets initialized with a key and a particular derived type like, {33, MyA}. I insert this set of initializations into a vector using std::initializer_list. The MyA and MyB constructors get properly called so I know the correct objects are getting constructed.

Being able to declare/instantiate an arbitrary number of item pairs at compile time will greatly reduce the complexity of my prototype code by eliminating much redundant code and allowing me to easily add additional sets of pairs as the code matures. itemVect1 in the model code works fine.

But when I make a call on MyAFunc(), itemVect1 executes the base class’s MyFunc().

Is there a way I can use this very powerful variadic code machinery and still maintain polymorphic access to various derived types which I want to pass in in the initializer list?

I built my model code off of the code in StackOverflow “Inserting a variadic argument list into a vector?”

struct My
{
  My() {}
  void MyFunc() {}
  virtual void MyAFunc() {}
  virtual void MyBFunc() {}
};

struct MyA : My
{
  MyA() : My() {}
  void MyAFunc() {}
};

struct MyB : My
{
  MyB() : My() {}
  void MyBFunc() {}
};

template< typename KeyT, typename ValueT >
struct ItemPair
{
  ItemPair( KeyT key, ValueT val )
    : key( key ), val( val ) {}
  KeyT key;
  ValueT val;
};

typedef ItemPair< const int, My > IPIntMy;

struct ItemPairVect
{
  ItemPairVect( std::initializer_list< IPIntMy > initList )
    : ipVect( initList ) {}

  std::vector< IPIntMy > ipVect;
};

int main()
{
  ItemPairVect itemVect1 { IPIntMy { 33, MyA {} }, IPIntMy { 44, MyB {} }, IPIntMy { 55, MyA {} }, IPIntMy { 66, MyB {} } }; // works fine
  itemVect1.ipVect[ 0 ].val.MyAFunc(); // doesn't behave polymorphically, that is, it calls MyFunc() instead
}

I tried changing My to My* in the typedef which is the normal way to make an object polymorphic, but had problems getting the initializer list to parse.

Aucun commentaire:

Enregistrer un commentaire