是否有 C++ 模板方法来循环不同的枚举?

Is there a C++ template way to loop on different enums?

在本主题中,我想知道 C++ 方法是否可以在不同的给定枚举上循环?下面的源码是我的提议,但是编译不了。

enum class Fruit : int
{
    UNKNOWN = 0,
    APPLE   = 1
};
 
enum class Vegetable : int
{
    UNKNOWN = 0,
    CARROT  = 1
};
 
static const std::map<std::string, Fruit> FRUITS_MAP
{
    {"unknown", Fruit::UNKNOWN},
    {"apple",   Fruit::APPLE}
};
 
static const std::map<std::string, Vegetable> VEGETABLES_MAP
{
    {"unknown", Vegetable::UNKNOWN},
    {"carrot",  Vegetable::CARROT}
};

template<typename T>
T myFunction(const std::string &iName)
{
    T result{T(0)};
    if (std::is_same<T, Fruit>::value)
    {
        const auto &found = FRUITS_MAP.find(iName);
        if (FRUITS_MAP.end() != found)
        {
            result = found->second;
        }
    }
    else if (std::is_same<T, Vegetable>::value)
    {
        const auto &found = VEGETABLES_MAP.find(iName);
        if (VEGETABLES_MAP.end() != found)
        {
            result = found->second;
        }
    }
    return result;
}

我无法编写仅更改 return 类型的方法,因为我得到 error: ambiguating

您只需在行中添加 constexpr 即可修复您的代码:

if constexpr (std::is_same<T, Fruit>::value)
...
else if constexpr (std::is_same<T, Vegetable>::value)

并像这样使用它:

std::cout << static_cast<int>(myFunction<Fruit>("apple")) << std::endl;
std::cout << static_cast<int>(myFunction<Vegetable>("carrot")) << std::endl;

如果您使用的是十年过时的编译器(为什么?),您可以简单地使用专门的模板:

template<typename T> T myFunction(const std::string &iName);

    template<>
Fruit myFunction<Fruit>(const std::string &iName)
{
    Fruit result{Fruit(0)};
    const auto &found = FRUITS_MAP.find(iName);
    if (FRUITS_MAP.end() != found)
    {
        result = found->second;
    }

    return result;
}

    template<>
Vegetable myFunction<Vegetable>(const std::string &iName)
{
    Vegetable result{Vegetable(0)};
    const auto &found = VEGETABLES_MAP.find(iName);
    if (VEGETABLES_MAP.end() != found)
    {
        result = found->second;
    }

    return result;
}

但在这里我们可以问为什么我们需要模板,因为简单地重载不同的名称具有相同的效果。这取决于实际用例。如果你有类型列表,你会带着一些 MTP 的东西走过去,这可能会有所帮助,如果它是将调用给定函数的手工代码,模板的东西就没有意义。