在命令数据结构中使用union

时间:2017-11-24 11:39:58

标签: c++ design-patterns command-pattern

我正在开发一个项目,我们将命令从上层传递给下层。

1。 一次处理单个命令

我们使用以下数据结构。

struct Command{
     //Different command types==> SEND / CREATE_TRANSACTION etc.
     CommandType type;

     //Associated parameters with every command
     union{
         struct{
             string remote_ip;
             uint16_t remote_port;
         }address;

         struct{
             string transaction_id;
             string transaction_details;
         }tsx;
         .
         .
         .
     }params;
};

我们为不同的命令传递不同的参数。联盟使其具有内存效率。

在C ++中有没有更好的方法(或设计模式)?

另一个。

2。 在单个命令对象中处理多个命令。

我可以这样做:

struct Command{
    uint64_t flag; //ORed value of different command types 

    //parameters
    struct{
        string remote_ip;
        uint16_t remote_port;
    }address;

    struct{
        string transaction_id;
        string transaction details;
    }tsx;
};

但是,它不是内存效率高的。

有没有更好的方法在单个对象中创建多个命令(在C ++中)?

3 个答案:

答案 0 :(得分:1)

您需要std::variantboost::variant。变体是类型安全的歧视联盟。

struct address {
    string remote_ip;
    uint16_t remote_port;
};

struct tsx {
    string transaction_id;
    string transaction details;
};

using command = std::variant<address, tsx>;

使用示例:

command c0{tsx{/* ... */}};
std::visit(
    overload(
        [](const address&){ /* handle address case */ },
        [](const tsx&)    { /* handle tsx case */ }
    ),
    c0
);

要了解如何实施overload及类似模式匹配实用程序,请参阅我的ACCU 2017讲座:"Implementing variant Visitation Using Lambdas"

答案 1 :(得分:-1)

您可以使用std :: variant和访问者模式。根据命令类型,访问者会以不同的方式处理有效负载数据。

documentation

这提供了工会不提供的类型安全

答案 2 :(得分:-1)

将工会用作“变体”,特别是为了“节省记忆”,几乎总是表明设计不佳。你需要质疑设计/规范是否有意义。是的,还有更好的方法:

如果这2个结构彼此无关,那么将它们保存为2个独立的结构(或类)。没有紧耦合设计程序比保存10-20字节的内存要重要得多。

否则,如果这两个结构确实有共同点,那么使“params”成为一个抽象基类,它包含结构的共同点。然后让“地址”和“tsx”继承该基类。