如何使用c ++在数组中存储不同的值类型?

时间:2011-05-30 19:41:08

标签: c++ arrays class templates generic-type-argument

我在配置类中要实现的某些功能有问题,我有一些不同类型的值,我想将它们存储在地图中。以前我使用ExtendedString类来存储所有数据,并在需要时使用模板函数将它们转换为所需类型。然后在我的配置类中有一个map<ExtendedString,vector<ExtendedString> >来存储配置文件中的所有密钥。这是我的ExtendedString类已经是这样的:

class ExtendedString : public std::string
{
public:
    ExtenedString() : public std::string
    {
    }
    template <class T> ExtenededString(T)
    {
        std::stringstream s;
        *this = s.str();
    }
    template <class T>T as(){
        istringstream s(*this);
        T temp;
        d >> temp;
        return temp;
    }
}

现在我想在加载配置文件时解析所有值,并且还具有在需要时转换为任何可能类型的功能。例如,如果我将一些值解析为int并且在我的运行时我需要该值作为字符串我希望能够立即强制转换,除此之外我不想在这种情况下使用boost,它是我的基类之一我不想将提升链接到我正在开发的每个项目。

3 个答案:

答案 0 :(得分:2)

一个经典解决方案是boost::any,或大量union。但我认为这两种方法都比他们解决的问题更麻烦。创建一个具有每个配置选项成员的Config类有什么问题?

答案 1 :(得分:1)

您可以编写“Value”类,然后为每种值编写子类,而不是将它们全部存储为字符串。

答案 2 :(得分:1)

我建议使用boost::any,因为它听起来像你正在寻找的。但是,如果你真的不想使用它,你可能能够像这样处理它。它可能不是最好的方法(这是我头脑中的第一件事) - 基本上它将值存储在你原来的类型和字符串中。如果您尝试将get作为原始类型,则返回该值,否则,它将使用std::stringstream尝试转换它。

注意:这不处理复制/分配,将d_data更改为您选择的共享指针来处理它。

#include <string>
#include <sstream>
#include <iostream>

class ConfigValue
{
    class HolderBase
    {
      protected:
        virtual void writeValueToStream(std::ostream& os) const = 0;

      public: 
        virtual ~HolderBase() { }

        template <class Type>
        Type getAs() const
        {
            std::stringstream ss;
            writeValueToStream(ss);

            Type temp;
            ss >> temp;
            return temp;
        }
    };

    template <class Type>
    class Holder : public HolderBase
    {
        Type d_value;

      protected:
        void writeValueToStream(std::ostream& os) const
        {
            os << d_value;
        }

      public:
        Holder(const Type& value)
        : d_value(value)
        {
            std::ostringstream oss;
            oss << value;
        }

        Type get() const
        {
            return d_value;
        }
    };

    HolderBase *d_data;

  public:
    template <class Type>
    ConfigValue(const Type& value)
    : d_data(new Holder<Type>(value))
    {
    }

    ~ConfigValue()
    {
        delete d_data;
    }

    template <class Type>
    Type get() const
    {
        if (Holder<Type> *holder = dynamic_cast<Holder<Type>*>(d_data))
        {
            return holder->get();
        }
        else
        {
            return d_data->getAs<Type>();
        }
    }
};

int main()
{
    ConfigValue cv = 10;

    std::cout << cv.get<std::string>() << std::endl;

    return 0;
}