我有一个需要能够接受不同类型的函数,然后将它们存储在单独的地图中。 (因此,如果它接收到一个整数,它应该进入整数映射等)。
我目前的代码:
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]
我的方法是否符合我的要求?有没有办法轻松将模板值转换回整数值?
答案 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;因此需要它。但当然有办法建立一个。一些例子:
void handle(int);
void handle(Thing);
template<typename T>
void set(T _value) {
handle(_value); // Or directly overload set
}
使用模板专精化同样有效。
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);
考虑到你想要每种类型的地图,我认为这样的事情适合你的情况:
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; }
};