【问题标题】:C++ Structure with unknown data types具有未知数据类型的 C++ 结构
【发布时间】:2013-05-26 19:45:23
【问题描述】:

我的程序读取用户的输入并创建简单的“表格”。用户在开始时指定列的数据类型和行数。

用户输入:

create table
add attribute string Name
add attribute int    Age
rows                   3

我现在需要根据用户的输入准备一个结构。我有这样的事情:

CTable
{
    unsigned   attributesCnt;
    string   * attributesNames;

    void    ** attributes;
};

因此,根据用户的输入,程序执行以下步骤:

CTable myTable;

myTable.attributesCnt = 2; // string "Name", int "Age"

myTable.attributesNames = new string[2];
myTable.attributesNames[0] = "Name";
myTable.attributesNames[1] = "Age";

attributes = new void[2]; // 2 attributes
attributes[0] = (void*) new string[3]; // there will be 3 rows
attributes[1] = (void*) new int[3];

我需要记住“attributes[0]”是字符串,“attributes[1]”也是 int。

这是“正确”的方式吗?

我只想使用标准库。

【问题讨论】:

  • 你需要像boost::variant这样的东西。
  • 问问自己:空隙的大小是多少?
  • @uberwulu:感谢您的评论。我使用指向 void 的指针,指针的大小取决于平台。这是真的吗?转发我不知道属性的数量和它们的类型。我需要 struct,我在哪里可以存储“2 int, 3 string”或“1 int, 1 string”或“1 int, 2 char, 3 string, 1 double”。
  • @CaptainObvlious:谢谢。我正在寻找使用标准库的解决方案。
  • Captain oblivious 带你走上正轨,看boost::any你也可能受益

标签: c++ data-structures type-conversion


【解决方案1】:

您正在寻找的是一个标记的联合,也称为变体。它允许您像常规联合一样在同一位置存储多种数据类型,但包括一个额外但单独的数据成员,指示它的类型。 C++ 标准库不包含变体,但它们很容易实现。

一旦你有了一个变体,你就可以将它应用到你的示例中,如下所示。

myTable.attributesNames[0] = "Name";
myTable.attributesNames[1] = "Age";

// I recommend using std::vector here instead of using new/delete yourself
attributes = new Variant*[2]; // 2 attributes
attributes[0] = new Variant("player name");
attributes[1] = new Variant(player_age);

以下示例显示了如何实现变体。

struct Variant
{
    enum Type
    {
        INT,
        STRINGPTR
    };

    Type    type_;
    union
    {
        int         int_;
        const char* stringptr_;
    }       data_;

    explicit Variant(int data) : type_(INT)
    {
        data_.int_ = data;
    }

    explicit Variant(const char *data) : type_(STRINGPTR)
    {
        data_.stringptr_ = data;
    }

    Type getType() const { return type_; }
    int getIntValue() const
    {
        if(type_ != INT)
            throw std::runtime_error("Variant is not an int");
        return data_.int_;
    }

    const char *getStringPtr() const
    {
        if(type_ != STRINGPTR)
            throw std::runtime_error("Variane is not a string");
        return data_.stringptr_;
    }
};

int main()
{
    Variant intval(1);
    Variant stringval("hello");

    std::cout << intval.getIntValue() << std::endl;
    std::cout << stringval.getStringPtr() << std::endl;
}

【讨论】:

  • 不客气。我仍然建议您至少看看boost::variantboost::any。它们是一个更完整的实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
  • 1970-01-01
  • 2011-11-07
  • 2020-09-06
相关资源
最近更新 更多