C ++模板到int

时间:2015-10-09 08:28:52

标签: c++ templates

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

我目前的代码:

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]

我的方法是否符合我的要求?有没有办法轻松将模板值转换回整数值?

2 个答案:

答案 0 :(得分:1)

你基本上说:

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的错误调用根本无法编译。

答案 1 :(得分:0)

假设你有像

这样的代码
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)。由于我们没有定义它,并且没有其他可行的函数可以调用,我们得到一个抱怨错误操作数类型的编译器消息。

回到您的问题,您需要的是不同的行为,具体取决于某些静态(编译时/类型级别)条件。不幸的是,在这种语言中,没有&#34;静态因为#&#34;因此需要它。但当然有办法建立一个。一些例子:

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