将不同类型的变量存储在C ++中的一个实体中

问题描述

我对C ++还是比较陌生,因此尝试寻找在一个实体下存储不同类型值的最佳方法。 上下文是,我有一个返回结构的函数,值之一可以是不同的类型。在任何时候,只会设置一个值。 对我来说,最好的情况是我可以做这样的事情:

Union Union1 {
int x;
char y;
double z;
}

executor(Union1 union1) {
  if(union1.x.isSet()) {
    doSomethingUsingX();
  } else if(union1.y.isSet()) {
    doSomethingElseUsingY();
  }
}

我不认为这是可能的,因为c ++联合使用相同的内存空间。 那有什么我可以用的吗?

解决方法

如果您使用的是C ++ 17或更高版本,请尝试std::variant。参见https://en.cppreference.com/w/cpp/utility/variant

如果早于C ++ 17,则可以尝试boost::variant

variant是进行联合的更好方法。它还记录了其中存储了什么东西,您可以使用std::visitvariant上调用类型重载函数。

就像这样,根据cppreference示例改编而成:

#include <iostream>
#include <variant>
#include <vector>

// helper type for the visitor #4
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
// explicit deduction guide (not needed as of C++20)
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

int main() {
  std::vector<std::variant<int,char,double>> v;
  v.emplace_back(1);
  v.emplace_back('c');
  v.emplace_back(2.7);

  for (const auto &x : v) {
    std::visit(
        overloaded{[](auto arg) { std::cout << "unknown " << arg << '\n'; },[](int arg) { std::cout << "int " << arg << '\n'; },[](double arg) { std::cout << "double " << arg << '\n'; },[](char arg) { std::cout << "char " << arg << '\n'; }},x);
  }
  return 0;
}

我在网上发现的这篇博客文章似乎也有助于解释其工作原理: https://pabloariasal.github.io/2018/06/26/std-variant/

,

您可以使用枚举来报告返回类型:

typedef enum
{
    x,y,z
}returnType;

typedef struct
{
    returnType rt;
    union
    {
        int x;
        char y;
        double z;
    };
}myStruct;

//...
myStruct AFunctionWithMyStructReturnType(int arg)
{
    myStruct ms;
    if(arg == 0)
    {
        ms.rt = returnType.x;
        ms.val = 10000;
    }
    else if(arg == 1)
    {
        ms.rt = returnType.y;
        ms.val = 200;
    }
    else
    {
        ms.rt = returnType.z;
        ms.val = 3.14;
    }
    return ms;
}
//...

myStruct S = AFunctionWithMyStructReturnType(arg);
switch(S.rt)
{
    case returnType.x:
        processX(S.val);
        break;

    case returnType.y:
        processY(S.val);
        break;

    case returnType.z:
        processZ(S.val);
        break;
}