如何在模板化函数中使用内置类型映射用户定义的枚举?

时间:2018-06-19 16:17:50

标签: c++ templates enums

我仍在尝试将较旧的程序更新为现代C ++,但是我还有另一个与模板有关的问题。 我正在使用libconfig ++处理程序配置,将纯文本数据写入配置文件。 您可以选择要写入文件的数据类型,并且库使用枚举来执行此操作(即Setting :: TypeString,Setting :: TypeBoolean等)

起初,我使用普通的重载,如下所示:

void Config::write_value(Setting& root, const string& key, const string& value) {
    if (!root.exists(key.c_str())) root.add(key.c_str(), Setting::TypeString) = value;
    else {
        Setting& s = root[key.c_str()];
        s = value;
    }
}

void Config::write_value(Setting& root, const string& key, const bool value) {
    if (!root.exists(key.c_str())) root.add(key.c_str(), Setting::TypeBoolean) = value;
    else {
        Setting& s = root[key.c_str()];
        s = value;
    }
}

但是这些函数是通用处理的候选对象,因为只需更改一个参数,就可以从该参数推导出库使用的类型。

问题是:我该怎么办? 我尝试使用conditional_t和is_same,但是编译器对我尝试的操作不满意,出了点问题,我认为这与枚举有关……

  

将枚举映射到参数类型的正确方法是什么?

这是我尝试过的一件事:

template<typename T>
using Type = std::conditional_t<std::is_same_v<T, bool>, Setting::TypeBoolean, void>;

template<typename T>
void write_value(libconfig::Setting& root, const std::string& key, const T& value)
{
    if (!root.exists(key.c_str())) root.add(key.c_str(), Type<T>) = value;
    else {
        Setting& s = root[key.c_str()];
        s = value;
    }
}

// Compiler error :
error C2275: 'Config::Type<bool>' :  illegal use of this type as an expression

感谢您的阅读:)

编辑 Setting :: *是一个枚举,实际上定义为Setting :: Type。

 enum Type
  {
    TypeNone = 0,
    // scalar types
    TypeInt,
    TypeInt64,
    TypeFloat,
    TypeString,
    TypeBoolean,
    // aggregate types
    TypeGroup,
    TypeArray,
    TypeList
  };

2 个答案:

答案 0 :(得分:2)

您在这里不解释对象root.add()如何从任意类型分配,但这似乎不是您当前要我们解决的问题...

您当前要解决的问题是将模板类型具体翻译为适当的枚举索引,为此,在c ++ 11中,我只需定义一个翻译器类即可:

template <class T> class ToMySetting {};
template <> ToMySetting<int> { static Setting index = {Setting::TypeInt}; };    
template <> ToMySetting<char*> { static Setting index = {Setting::TypeCStr}; };    
template <> ToMySetting<bool> { static Setting index = {Setting::TypeBool}; };

然后您可以将write_value函数中的内容用作ToMySetting<T>::index

在较新的版本(c ++ 17)中,我倾向于使用if constexpr语法仅一次定义ToMySetting转换器类主体。

答案 1 :(得分:0)

在根据@ gem-taylor答案进行了一些研究之后,我得到了下面的版本,该版本可以根据需要工作。仍需要进行一些调整以包括std :: string版本,但这不是必需的。

{ 'year': 2018, 'month': 6, 'day': 14 }

编辑:为完整起见,这是char数组和std :: string的2个专业化:

template <class T> struct ToMySetting;
template <> struct ToMySetting<bool>        { static constexpr libconfig::Setting::Type index = libconfig::Setting::TypeBoolean; };
template <> struct ToMySetting<uint32_t>    { static constexpr libconfig::Setting::Type index = libconfig::Setting::TypeInt; };
template <> struct ToMySetting<uint64_t>    { static constexpr libconfig::Setting::Type index = libconfig::Setting::TypeInt64; };
template <> struct ToMySetting<float>       { static constexpr libconfig::Setting::Type index = libconfig::Setting::TypeFloat; };
template <> struct ToMySetting<const char*> { static constexpr libconfig::Setting::Type index = libconfig::Setting::TypeString; };

template<class T>
void write_value(libconfig::Setting& root, const std::string& key, const T& value)
{
    if (!root.exists(key.c_str())) root.add(key.c_str(), ToMySetting<T>::index) = value;
    else {
        libconfig::Setting& s = root[key.c_str()];
        s = value;
    }
}