是否可以将 std::string 转换为 std::cin 中的枚举类?

is it possible to convert std::string into enum class in std::cin?

提问人:Caparso 提问时间:8/3/2023 更新时间:8/4/2023 访问量:52

问:

我是 cpp 的新手。假设我们有一个如下类:

 class Animal {
    public:
        enum class Group {mammal, bird, reptile};
    private:    
        Group group;
}

现在我想以这种方式初始化它:

Animal::Group g;
std::cin >> g;
std::unique_ptr<Animal> dog = std::make_unique<Animal>(std::move(g));

我试图重载如下 istream 并使其成为朋友,但它不起作用。class Animal

auto string_to_vlt(std::string const s) -> std::optional<Human::Violation>
{
    if (s == "mammal")     return Animal::Group::mammal;
    if (s == "bird")       return Animal::Group::bird;
    if (s == "reptile")    return Animal::Group::reptile;
    return std::nullopt;
}

auto operator>>(std::istream& is, Animal::Group v) -> std::istream& // friend function
{
    auto s = std::string();
    if (!(is >> s)) {
        return is;
    }
    if (auto result = string_to_vlt(s)) {
        v = *result;
    }
    return is;
}

有什么想法吗?可能吗?

C++ 枚举类

评论

2赞 user17732522 8/3/2023
"但它不起作用“:它怎么不起作用?:这是按值计算参数。你真的想要那个吗?另外,如果导致分支被占用,您期望具有什么价值?此外,继续枚举类型绝对不做任何事情,并且不能从您定义它的方式构造。所以应该编译失败。Animal::Group vgauto result = string_to_vlt(s)elsestd::moveAnimalGroupstd::make_unique<Animal>(std::move(g))
1赞 tadman 8/3/2023
这就是 std::map 映射表可以派上用场的地方。尽量避免将“成堆的陈述”作为解决问题的方法。if
4赞 user17732522 8/3/2023
您正在调用重载,并且您似乎打算让函数修改 的值。但你正在传递副值。因此,您只是在修改 中的副本。如果要在该行中进行修改,则需要按引用传递operator>>std::cin >> g;gggoperator>>g
2赞 Toby Speight 8/3/2023
按值传递给 没有多大意义。如果你想让你的作业做任何有用的事情,你就要传递一个参考voperator>>
3赞 Toby Speight 8/3/2023
如果转换不成功,设置流的故障位可能也是一个好主意。

答:

1赞 Marek R 8/4/2023 #1

有一个很酷的库可以解决这个问题 魔术枚举.

它可以使代码无需大量编码即可工作:

#include <iostream>
#include <memory>
#include <magic_enum.hpp>
#include <magic_enum_iostream.hpp>

using namespace magic_enum::ostream_operators; 
using namespace magic_enum::istream_operators; 

class Animal {
public:
    enum class Group {
        mammal,
        bird,
        reptile,
    };

    explicit Animal(Group g) : group { g } { 
        std::cout << "making: " << group << '\n';
    }

    ~Animal()
    {
        std::cout << "removing: " << group << '\n';
    }

private:
    Group group;
};

int main()
{
    Animal::Group g;
    while (std::cin >> g) {
        auto dog = std::make_unique<Animal>(g);
    }
    return 0;
}

https://godbolt.org/z/ae7nbvbEq

免责声明:请注意,此库利用了一些编译器特定的功能,因此不能保证它始终有效。请参阅限制