如何在C++17中使用“变量”和“访问”?[已关闭]

fcipmucu  于 2023-03-14  发布在  其他
关注(0)|答案(1)|浏览(145)

**已关闭。**此问题需要debugging details。当前不接受答案。

编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将有助于其他人回答问题。
昨天关门了。
Improve this question
我有一个测试a(),B(),c()onclass A,B,C的需求。使用它最简单的方法是要求3*3 if-else。我想尝试3+3 if-else

Class A
{
...
public:
int k(){...};
...
};

Class B
{
...
public:
int k(){...};
...
};

Class C
{
...
public:
int k(){...};
...
};

template<class T>
void a(const T& g, int m)
{
...
g.k();
...
}

template<class T>
void b(const T& g, int m, int n)
{
...
g.k();
...
}

template<class T>
void c(const T& g, int m, int n, int o)
{
...
g.k();
...
}

然后我看到了variant,并使用它来实现3+3 if-else。

int main(int argc, char** argv)
{
std::variant<std::monostate, A, B, C> x;//For some reason A, B, C do not have the default constructors
if(argv[1]=="A") x=A(...);
else if(argv[1]=="B") x=B(...);
else if(argv[1]=="C") x=C(...);

//error 1 How to use a function that takes more than two arguments directly here?
if(argv[2]=="a") std::visit(a, x, atoi(argv[2]));
else if if(argv[2]=="b") std::visit(b, x, atoi(argv[2]), atoi(argv[3]));
else if(argv[2]=="c") std::visit(c, x, atoi(argv[2]), atoi(argb[3]), atoi(argv[4]));

//error 2 Since A, B, C do not have the default constructors, monostate does not have the k() required by a(), b(), c().
if(argv[2]=="a") std::visit([&](const auto& G){a(G, atoi(argv[2]));}, x);
else if if(argv[2]=="b") ...;
else if(argv[2]=="c") ...;
}

请寻找更好的方法或解决上述error 1和error 2,非常感谢。
但不管怎样,我实际上是想看看是否有更好的方法来编写它,避免3*3的if-else。

//i want to avoid
int main(int argc, char** argv)
{
   if(argv[1]=="A")
   {
      A tmp_class;
      if(argv[2]=="a") a(tmp_class);
      else if(argv[2]=="b") b(tmp_class);
      else c(tmp_class);
   }
   else if(argv[1]=="B")
   {
      B tmp_class;
      if(argv[2]=="a") a(tmp_class);
      else if(argv[2]=="b") b(tmp_class);
      else c(tmp_class);
   }
   else
   {
      C tmp_class;
      if(argv[2]=="a") a(tmp_class);
      else if(argv[2]=="b") b(tmp_class);
      else c(tmp_class);
   }
}

有没有更好的方法来达到3+3 if-else?

//pseudocode
    int main(int argc, char** argv)
    {
       T tmp_class;
       //3 if-else
       if(argv[1]=="A") tmp_class=A(...);
       else if(argv[1]=="B") tmp_class=B(...);
       else tmp_class=C(...);
       //+
       //3 if-else
       if(argv[2]=="a") a(tmp_class);
       else if(argv[2]=="b") b(tmp_class);
       else c(tmp_class);
    }
c3frrgcw

c3frrgcw1#

使用std::visit的最简洁的方法是创建一个overloadedstruct,它派生自您创建的每个lambda,以处理您的std::variant在任何给定时间可能持有的所有潜在类型。
在这个例子中,我没有定义任何构造函数,所以std::monostate不是显式需要的,但是我还是添加了它,向您展示如何处理std::variant没有赋值的情况;

template<class... Ts> 
struct overloaded : Ts... { using Ts::operator()...; };
// Deduction guide is only needed pre C++20.
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

struct A {
    void print(const std::string_view msg) const {
        std::cout << msg << '\n';
    }
};
struct B {};
struct C {};

using types = std::variant<std::monostate, A, B, C>;

int main()
{
    // You can either assign an already created object to the variant.
    types values = B{};

    // Or you can create the object in place.
    values.emplace<A>(/* Here you can pass constructor arguments if required. */);

    const std::string_view msg{ "'A' class" };

    std::visit(overloaded {
        // Note that I'm capturing the variable 'msg' and using it in the lambda.
        [&msg](const A& a) { a.print(msg); },
        [](const B& b) { std::cout << "B\n"; },
        [](const C& c) { std::cout << "C\n"; },
        [](std::monostate) { std::cout << "Nothing\n"; }
        }, values);

    // Note that you can also use the following free functions
    // to check/get the object of a specific type from the variant.
    if (std::holds_alternative<A>(values)) {
        // Holds 'A' so lets use std::get to get a reference to the object.     
        const A& a{ std::get<A>(values) };
    }

    if (const auto* ptr{ std::get_if<B>(&values) }) {
        // Holds 'B'.
    }
}

相关问题