【问题标题】:C++ Return either a string or int without auto [closed]C ++返回没有自动的字符串或int [关闭]
【发布时间】:2019-05-06 08:30:52
【问题描述】:

我正在编写一个带有 Column 类的 SQL 控制器。 Column 类具有属性

  1. 名称(字符串)
  2. 类型(枚举列表)
  3. 索引(行中)
  4. 价值

但值可以是字符串或整数。在现实中,无论如何,在 sqlite 中,所有值都作为char 数组返回。但最后我希望用户能够做类似的事情

Column column = row->GetColumn(1);
value = column->GetValue();

现在我无权访问auto,所以我什至不确定如何在任何级别上处理这个问题,无论是来自调用者(他们如何一定知道值类型是什么?)和来自 Column类。

【问题讨论】:

  • 您的列类的用户必须通过您创建的方法查询该类的类型,例如GetValueType
  • GetValue() 返回一个std::variant(或boost::variant,如果您使用的是C++ 17 之前的编译器),根据实际SQL 类型填充正确的数据。然后调用者可以根据其中实际存储的内容从variant 中提取数据。
  • @RemyLebeau 这似乎是正确的解决方案,所以你为什么不把它写下来并收集你的互联网积分?
  • @CoffeeTableEspresso 它仍然需要用户知道该列将存储的类型。他们显然可以调用holds_alternative,但是如果将来变体模板发生更改,很多代码都会中断,因为ICU_ 无法访问auto。在我看来,最好的解决方案是将类型内部存储在列中并使用getTYPEValue() 方法。
  • @Kyle SQL 值可以是有限数量的类型。 variant 可以定义为包含所有可用类型,其中一些类型(如 char 数组、不同大小的整数等)可以抽象为更通用的类型,以减少 variant 需要的类型数量处理(即char..short..int -> int, char[]..varchar -> std::string 等)。

标签: c++ sql sqlite


【解决方案1】:

GetValue() 返回一个 std::variant(或 boost::variant,如果您使用的是 C++17 之前的编译器),它根据实际 SQL 类型填充了正确的数据。然后调用者可以根据实际存储的内容从变体中提取数据:

typedef std::variant<std::monostate, int, std::string, and_so_on...> SQLValue;
...

SQLValue value = column->GetValue();

if (std::holds_alternative<std::monostate>(value))
{
    // you can use this for null data...
}
else if (std::holds_alternative<int>(value))
{
    int ivalue = std::get<int>(value);
    ...
}
else if (std::holds_alternative<std::string>(value))
{
    std::string svalue = std::get<std::string>(value);
    ...
}
else ...

或者:

SQLValue value = column->GetValue();

if (std::get_if<std::monostate>(&value))
{
    // you can use this for null data...
}
else if (int *p_ivalue = std::get_if<int>(&value))
{
    int ivalue = *p_ivalue;
    ...
}
else if (std::string *p_svalue = std::get_if<std::string>(&value))
{
    std::string svalue = *p_svalue;
    ...
}
else ...

或者:

SQLValue value = column->GetValue();

switch (value.index())
{
    case 0:
    {
        // you can use this for null data...
        break;
    }

    case 1:
    {
        int ivalue = get:::get<1>(value);
        ...
        break;
    }

    case 2:
    {
        std::string svalue = std::get<2>(&value);
        ...
        break;
    }

    case ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 2018-05-13
    相关资源
    最近更新 更多