0

I'm trying to create a generic function toStr() for several enum classes but I'm having some issues.

I have these enum classes and maps to convert the value of the enums to string.

'''

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"}
};
'''

So my first option was trying to create just one function

'''
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:
}
'''

While using this function I get compiling errors because the compiler resolves the type at compile time and there is always a type accesing a map that is not correct. I understand that.

So my second alternative was specializing toStr() with each enum type but I got multiple definitions while compiling.

'''

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];
}

'''

Is what I'm trying even possible? Could you shed some light about this?

Many thanks

2
  • Thanks, I'm using C++17 so I will try adding contrexpr to the comparission. Commented Sep 23, 2022 at 22:25
  • I advocate making these sperate functions. Adding an overload for each type not only keeps the functions small and simple. but allows other to write their own enums and their own toStr that will work with your code as toStr is your customization point. Commented Sep 23, 2022 at 22:27

1 Answer 1

0

First options requires C++17 and 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";
    }
}

So my second alternative was specializing toStr() with each enum type but I got multiple definitions while compiling.

template are implicitly inline, but not specialization, so you need inline to avoid multiple definition:

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];
}

Alternative would be simple overloads:

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];
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! The C++17 "if constrexpr" option works perfectly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.