c++模板转换为int

C++ template to int

本文关键字:int 转换 c++      更新时间:2023-10-16

我得到一个函数,它需要能够接受不同的类型,然后将它们存储在单独的映射中。(因此,如果它接收到一个整数,它应该进入整数映射,等等)

我的当前代码:

template<typename T>
void set(const char* _key, T _value) {
    DateTime* dt = new DateTime();
    if(std::is_same<T, int>::value) {
        settingsInt.insert(std::pair<const char*, int>(_key, _value));
        printf("[%s][MESSAGE] Added integer setting (%s, %i)n", dt->getDateTimeStamp(), _key, _value);
    } else if(std::is_same<T, const char*>::value) {
        printf("[%s][MESSAGE] Added string setting (%s, %s)n", dt->getDateTimeStamp(), _key, _value);
    } else if(std::is_same<T, double>::value) {
        printf("[%s][MESSAGE] Added double setting (%s, %f)n", dt->getDateTimeStamp(), _key, _value);
    } else {
        printf("[%s][WARNING] Trying to set setting of unknown type! (%s)n", dt->getDateTimeStamp(), _key);
    }
}

printf函数正确显示,if语句正确查看传递的类型。但是,当我尝试将值插入到映射中时,会得到以下错误:

error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]

我的方法能达到我想要的效果吗?是否有一种方法可以轻松地将模板值转换回其整数值?

你可以说:

if (type of x is int)
   insert x to the int map
if (type of x is char*)
  insert x to the char* map

但是这行不通。编译器要检查插入语句的类型是否正确。两个insert语句

insert x to the int map
insert x to the char* map

不能同时是正确的。保护每个语句的条件是真还是假是无关紧要的。语句可以永远不执行,但无论如何必须是类型正确的。

正确的方法是为每个允许的类型重载set函数。不需要编写模板。也不需要处理默认情况,对set的献礼根本不会编译。

假设你有这样的代码

template<typename T>
void set(T _value) {
  if(std::is_same<T, int>::value) {
    _value + 42;
  }
}

struct Thing {}表示。编译器将在编译时检查代码中所有语句和表达式的类型(显然,c++是静态类型的),并且在实例化上述模板之后,它将检查类似于以下内容:

void set(Thing _value) {
  if (false) {
    _value + 42;
  }
}

编译器不关心if分支是否被占用,它看到表达式_value + 42,因此试图找到operator+(Thing, int)。由于没有定义该函数,并且没有其他可行的函数可调用,因此会得到一个编译器消息,抱怨操作数类型错误。

回到你的问题,你想要的是不同的行为取决于一些静态(编译时/类型级别)的条件。不幸的是,在该语言中没有"静态if"这样的东西,因此这是必需的。当然,有很多方法可以建造一个。一些例子:

a)使用函数重载
void handle(int);
void handle(Thing);
template<typename T>
void set(T _value) {
  handle(_value); // Or directly overload set
}

使用模板专门化也一样。

b)使用std::conditional
struct IntHandler {
  static void handle(int);
};
struct NoHandler {
  template<typename T>
  static void handle(T) {}
};
//
using handler = typename std::conditional<
  std::is_same<T, int>::value, IntHandler, NoHandler>::type;
handler::handle(_value);
c)在您的例子中,使用继承

考虑到您需要每种类型的映射,我认为像这样的东西将适合您的情况:

template<typename...>
struct Map {};
template<typename First, typename... Rest>
struct Map<First, Rest...> : public Map<Rest...> {
  std::map<char const *, First> _map;
  void set(char const * key, First value) { _map[key] = value; }
};