尝试为多个枚举类创建 str 的泛型强制转换

Trying to create a generic cast to str for several enum classes

提问人:Ojotuno 提问时间:9/24/2022 更新时间:9/24/2022 访问量:37

问:

我正在尝试为几个枚举类创建一个通用函数 toStr(),但我遇到了一些问题。

我有这些枚举类和映射来将枚举的值转换为字符串。

'''

enum class InitFields : int32_t
{
    userRightsPath = 1,
    configurationDataPath,
    configFile
};

static std::map<InitFields, QString>  s_initField2str
{
    {InitFields::rhSystem, "rhSystem"},
    {InitFields::number, "number"},
    {InitFields::userRightsPath,"userRightsPath"}
};

enum class UserRole : int32_t
{
    Administrator=1,
    Superuser,
    Operator
};

static std::map<UserRole, QString> s_userRole2str
{
    {UserRole::Operator, "Operator"},
    {UserRole::Administrator,"Administrator"},
    {UserRole::Superuser,"Super-User"}
};
'''

因此,我的第一个选择是尝试只创建一个函数

'''
template <typename T>
static QString const toStr(T enumt)
{
    QString value = "";

    if (std::is_same<T, InitFields>())
    {
        value = s_initField2str[enumt];
    }
    else if (std::is_same<T, UserRole>())
    {
        value = s_userRole2str[enumt];
    }
    else 
    {
        value = "Error converting the enum";
    }

    return value:
}
'''

使用此函数时,我遇到编译错误,因为编译器在编译时解析类型,并且总是有一个类型访问不正确的映射。我明白这一点。

因此,我的第二个选择是将每个枚举类型专门用于 Str(),但我在编译时得到了多个定义。

'''

template <typename T>
static QString const toStr(T enumt)
{
    return "Error converting the enum";
}

template <>
static QString const toStr<InitFields>(InitFields enumt)
{
     return s_initField2str[enumt];
}

template<>
QString const toStr<UserRole>(UserRole enumt)
{
    return s_userRole2str[enumt];
}

'''

我正在尝试的可能吗?您能对此进行一些说明吗?

非常感谢

C 枚举类 C++ 模板

评论

0赞 Ojotuno 9/24/2022
谢谢,我正在使用 C++17,所以我将尝试将 contrexpr 添加到比较中。
0赞 NathanOliver 9/24/2022
我主张使这些单独的功能。为每种类型添加重载不仅可以使函数保持小而简单。但允许其他人编写他们自己的枚举和他们自己的枚举,这些枚举将与您的代码一起使用,就像您的自定义点一样。toStrtoStr

答:

0赞 Jarod42 9/24/2022 #1

第一个选项需要 C++17 和:if constexpr

template <typename T>
static QString const toStr(T enumt)
{
    if constexpr (std::is_same<T, InitFields>())
    {
        return s_initField2str[enumt];
    }
    else if constexpr (std::is_same<T, UserRole>())
    {
        return s_userRole2str[enumt];
    }
    else 
    {
        return "Error converting the enum";
    }
}

因此,我的第二个选择是将每个枚举类型专门用于 Str(),但我在编译时得到了多个定义。

template是隐式的,但不是专用的,所以你需要避免多重定义:inlineinline

template <typename T>
QString toStr(T enumt)
{
    return "Error converting the enum";
}

template <>
inline QString toStr<InitFields>(InitFields enumt)
{
     return s_initField2str[enumt];
}

template<>
inline QString toStr<UserRole>(UserRole enumt)
{
    return s_userRole2str[enumt];
}

另一种方法是简单的重载:

template <typename T>
QString toStr(T enumt) // = delete;
{
    return "Error converting the enum";
}

inline QString toStr(InitFields enumt)
{
     return s_initField2str[enumt];
}

inline QString toStr(UserRole enumt)
{
    return s_userRole2str[enumt];
}

评论

0赞 Ojotuno 9/24/2022
谢谢!C++17 “if constrexpr” 选项可以完美地工作。