提问者:小点点

根据布尔值在两个typedef结构之间切换


我有一个不同功能的类。 该类使用两个typedef结构。

typedef struct {
   struct head;
   struct data1;
} data_struct_1;

typedef struct {
   struct head;
   struct data2;
} data_struct_2;

如果bool为true,则应使用data_struct_2,否则应使用data_struct_1。 当创建对象并将其作为membervariable存储在构造函数中时,将传递布尔值。

现在有不同的函数和声明,如

int calc_mean(data_struct_1 ds, int a){ ... }

data_struct_1 ds;
ds.data1 = 5;

有没有一种优雅的方式,可以让我在那两个结构之间切换,而不用实现几十个if-case,并用头中相应的结构复制所有相关的函数? 首先,我考虑的是继承和覆盖相关函数,如果bool为真。 但是函数中的头不同,所以这是行不通的,可能有一些像占位符或模板之类的东西,但是我对C++还是很陌生的


共3个答案

匿名用户

如果布尔值是编译时值,则可以使用std::conditional:

template <boolean B>
using my_type = std::conditional_t<B, data_struct_1, data_struct_2>;

但布尔值似乎是运行时值,因此我将使用std::variantstd::visit:

class C
{
    using Data = std::variant<data_struct_1, data_struct_2>;
    Data m_data;
public:
    C(bool b) : m_data{b ? Data{data_struct_1{}} : Data{data_struct_2{}}} {}


    auto mean() const {
        return std::visit([](const auto& data){ return int calc_mean(data, 42); }, m_data);
    }
};

匿名用户

您有几种选择:

  1. 如果类型在概念上是相同类型的东西(即它们具有相同的接口并且可以相互替换),则可以:
    1. 创建抽象基类型并使用多态性更改实例化的具体类型
    2. 将所有使用这些类型的地方更改为模板,更改在运行时实例化的模板,然后依靠编译时“duck-typing”来完成其余的工作

匿名用户

一种可能是使用std::variant:

typedef std::variant<data_struct_1, data_struct_2> data_struct_1_or_2;

void foo(data_struct_1_or_2 ds) {
    if (auto ds1 = std::get_if<data_struct_1>(&ds)) {
        // use ds1, which is type data_struct_1*
    } else if (auto ds2 = std::get_if<data_struct_2>(&ds)) {
        // use d2, which is type data_struct_2*
    }
}

void bar(data_struct_1_or_2 ds) {
    foo(ds); // Don't need to use an if statement here
}

如果您有一个data_struct_1data_struct_2,并且希望传递对对象的引用,而不是一个副本,则可以使用std::variant中的指针(尽管它会与std::get_if有点混淆,因为您最终会得到指向指针的指针):

typedef std::variant<data_struct_1*, data_struct_2*> data_struct_1_or_2_ptr;