2016-12-06 36 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; 
    } 

} 
相关问题