异构数组中的元素可以知道它是什么模板类型的吗?

时间:2016-12-06 18:57:14

标签: c++ class templates virtual rtti

我想在数组中创建一大堆对象,我希望它们是不同的模板类型。目标是我想更新这些对象中的每一个并将它们保存的变量值存储为字符串。例如:

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,所以我可以迭代所有对象并将变量值转换为string。我不确定如何/如果我能做到这一点。基本上是这样的:

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

通常你会有一个指向基类的指针向量,让虚拟化处理要调用的函数。但在这种情况下,我想知道是否可以根据模板的类型来处理它。我想过RTTI,能够识别出什么类型&#34;变量&#34;是并调用适当的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();

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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; 
    }

} 
相关问题