2017-01-28 63 views
3

我有一個基地std::vector和一個std::initializer_list<Attribute*>,它是由派生類Attribute類組成的函數的參數。應該替換現有類型,添加新類型

class Attribute {}; 
class Place : public Attribute {}; 
class Time : public Attribute {}; 
class Way: public Attribute {}; 

Place* place = new Place(); 
Time* time = new Time(); 
Way* way = new Way(); 
Place* place2 = new Place(...); 
Time* time2 = new Time(...); 

auto baseList = std::vector<Attribute*>({ place, time, way }) 

void updateBaseList(std::vector<Attribute*>& v, std::initializer_list<Attribute*> l); 

什麼updateBaseList必須做的是,如果l元素的類型等於一體的baseList,更新baseListl的一個值。如果類型不baseList遇到的,它必須添加到它。如果要查找的類型

注意不Attribute*,取而代之的則是派生類。

我嘗試

void updateBaseList(std::vector<Attribute*>& v, std::initializer_list<Attribute*> l) { 
    bool found; 
    for (auto listIt = l.begin(); listIt != l.end(); ++listIt) { 
     found = false; 
     for (auto attrIt = baseList.begin(); attrIt != baseList.end(); ++attrIt) { 
      if (typeid(**listIt) == typeid(**attrIt)) { 
       *attrIt = *listIt; 
       found = true; 
       break; 
      } 
     } 
     if (!found) { 
      baseList.push_back(*listIt); 
     } 
    } 
} 

typeid(**listIt)typeid(**attrIt)總是返回Base

目標

如果我打電話updateBaseList(baseList, { time2, place2 }) baseList應該{ place2, time2, way }

回答

2

你需要做的類層次結構多態。這樣做的一個好方法是通過添加virtual ~Attribute() { }析構函數:

struct Attribute 
{ 
    virtual ~Attribute() { } 
}; 

你的代碼,然後works as expected

{ 
    auto baseList = std::vector<Attribute*>({ place0, time0 }); 

    updateBaseList(baseList, {place2, time2, way0}); 
    assert(baseList[0] == place2); 
    assert(baseList[1] == time2); 
    assert(baseList[2] == way0); 
    assert(baseList.size() == 3); 

    updateBaseList(baseList, {place0}); 
    assert(baseList[0] == place0); 
    assert(baseList[1] == time2); 
    assert(baseList[2] == way0); 
    assert(baseList.size() == 3); 
} 

無關,但你可以讓你的baseList實現更容易用C閱讀++ 11範圍for循環:

void updateBaseList(std::vector<Attribute*>& v, std::initializer_list<Attribute*> l) 
{ 
    for (auto& litem : l) 
    { 
     bool found = false; 
     for (auto& attr : baseList) 
     { 
      if (typeid(*litem) != typeid(*attr)) continue; 

      attr = litem; 
      found = true; 
      break; 
     } 

     if (!found) 
     { 
      v.push_back(litem); 
     } 
    } 
} 

您可以還可以利用標準算法來避免有狀態found變量:

void updateBaseList(std::vector<Attribute*>& v, std::initializer_list<Attribute*> l) 
{ 
    for (auto& litem : l) 
    { 
     const auto found = std::find_if(std::begin(v), std::end(v), [&](Attribute* p) 
             { 
              return typeid(*litem) == typeid(*p); 
             }); 

     if (found == std::end(v)) 
     { 
      v.push_back(litem); 
     } 
     else 
     { 
      *found = litem; 
     } 
    } 
} 
相關問題