2016-12-06 29 views
0

我想在數組中創建一大堆對象,並且我希望它們是不同的模板類型。目標是我想更新每個這些對象並將它們保存的變量值存儲爲一個字符串。例如:異構數組中的元素是否可以知道它是什麼模板類型?

template <typename T> struct VariableToString 
{ 
    VariableToString(T& varArg) : variable(varArg){}; 
    T& variable; 
    std::string variableAsString; 

    void update() 
    { 
     variableAsString = std::to_string(variable); // <--- Compiler knows which overloaded function to call, but not through a pointer to this struct at runtime 
    } 
} 

然後我想有這些對象的一個​​std :: vector的,這樣我就可以在所有的對象迭代和變量值轉換爲字符串。我不知道如何/如果我能做到這一點。基本上是這樣的:

std::vector<Idontknow*> myVector; 
for (auto i : myVector) i->update(); 

通常你會有一個向基類指針的向量,並讓虛擬化處理調用哪個函數。但在這種情況下,我想知道是否可以根據模板的類型進行處理。我想過RTTI,是否能夠確定什麼類型的「變量」,並調用相應的to_string()函數?

我必須爲每一個創建一個新的派生版本嗎?像:

struct BaseClass 
{ 
    virtual void update() = 0; 
} 

struct DoubleToString : BaseClass 
{ 
    double& variable 
    void update() override; 
} 

std::vector<BaseClass*> myVector; 
for (auto i : myVector) i->update(); 
+0

沒有「模板類型」或「模板類型」或任何類似的東西。 –

+0

如果你的類型依賴於一個基類,那麼模板沒有什麼特別之處。模板的一個實例只是一個類型。該類型的對象不得與其構建的模板類型相關。對於您的設計,它看起來很簡單,就是從一個普通的基類中派生出來,並簡單地完成這項工作 – Klaus

回答

1

讓你的派生類模板:

struct BaseClass 
{ 
    virtual void update() = 0; 
} 
template <typename T> struct VariableToString : BaseClass{/*...*/} 

然後你可以使用它,你想要的方式:

std::vector<BaseClass*> myVector; 
/*...*/ 
for (auto i : myVector) i->update(); 

雖然考慮使用智能指針代替,例如

std::vector<std::unique_ptr<BaseClass>> myVector; 
/*...*/ 
for (auto i : myVector) i->update(); 

或者使用shared_ptr<>代替unique_ptr

+0

當然,我錯過了它,它非常明顯。謝謝。 – Zebrafish

0

如果您只有一個模板類,那麼完成這項工作非常容易。但是,如果你的模板是任何其他類的包裝器,只要它是從一個公共基類派生的,就可以使用它來獲得稱爲正確的虛擬方法。這與RTTI無關!

使用包裝可以使用沒有公共基類的類。而且你也可以專門化你的包裝類,它具有相同的語義但不同的名稱和簽名的功能。

class Base 
{ 
    public: 
     virtual std::string ToString() = 0; 

     virtual ~Base() {} 
}; 

class A 
{ 
    public: 
     std::string GetString() { return "From Type A"; } 
}; 

class B 
{ 
    public: 
     std::string GetString() { return "From Type B"; } 
}; 


class C 
{ 
    public: 
     void Name(std::string& name) 
     { 
      name="From Type C"; 
     } 
}; 

template < typename Inner > 
class Wrapper: public Base, Inner 
{ 
    public: 
     std::string ToString() override { return Inner::GetString(); } 
}; 

template <> 
class Wrapper<C>: public Base, C 
{ 
    public: 
     std::string ToString() override 
     { 
      std::string name; 
      C::Name(name); 
      return name; 
     } 
}; 

int main() 
{ 
    std::vector< Base*> elements; 

    elements.push_back(new Wrapper<A>); 
    elements.push_back(new Wrapper<B>); 
    elements.push_back(new Wrapper<C>); 

    for (auto& el: elements) 
    { 
     std::cout << el->ToString() << std::endl; 
    } 

    for (auto& el: elements) 
    { 
     delete el; 
    } 

} 
相關問題