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

Ojotuno
  • 21
  • 6
  • Thanks, I'm using C++17 so I will try adding contrexpr to the comparission. – Ojotuno Sep 23 '22 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. – NathanOliver Sep 23 '22 at 22:27

1 Answers1

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];
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302