【发布时间】:2022-01-17 03:17:22
【问题描述】:
考虑以下宏:
#define checkExists(map, it, value) {\
it = map.find(value);\
if(it == map.end()){\
if(!strcmp(typeid(value).name(), "Ss")){ /* value is an std::string */\
manageError(ERR_CANT_FIND_RESSOURCES, "in %s __ failed to find %s in map %s", __FUNCTION__, value.c_str(), #map);\
\
}else if(!(strcmp(typeid(value).name(), "Pc") * strcmp(typeid(value).name(), "PKc"))){ /* value is either char* or const char* */\
manageError(ERR_CANT_FIND_RESSOURCES, "in %s __ failed to find %s in map %s", __FUNCTION__, value #map); /* problem here because for gcc value could be an std::string */ \
\
} else \
manageError(ERR_CANT_FIND_RESSOURCES, "in %s __ failed to find 0x%04X in map %s", __FUNCTION__, value #map); /* problem here because for gcc value could be an std::string */\
}\
}
manageError 也是一个调用函数logWarning 的宏,它只接受基本类型(例如int、char* ...)。原型是:
#define manageError(error_code, error_str, ...) {\
{\
logWarning(error_str, ##__VA_ARGS__);\
return error_code;\
}\
}
int logWarning(const char* printf_format, ...);
所以如果我的value 是std::string,我将给manageError 一个const char *。
似乎 checkExists 没有评估编译时间...所以 gcc 非常聪明,它不允许我最后两个 manageError 调用,因为它将 value 视为 std::string 或这是不可能的,因为std::string 只有在第一种情况下才有可能。
例如,这不起作用:
std::string foo;
checkExists(myMap, myMapIterator, foo);
gcc 输出:
error: cannot pass objects of non-trivially-copyable type 'const string {aka const struct std::basic_string<char>}' through '...'
你知道我该如何解决这个问题吗?
编辑
该机制的想法是在发生错误时能够离开当前功能。例如:
int func(){
std::string foo;
checkExists(myMap, myMapIterator, foo); //leaves the function if foo is not found inside myMap
return 0;
}
所以我必须使用宏才能离开该功能(我无法使用模板)。
【问题讨论】:
-
@Jarod42 我正在使用 C++(不要介意类似 C 的指令)。
-
@Jarod42 更新了它,但认为它会提供相同的解决方案,因为 C 方法在 C++ 中有效。
-
模板怎么样?
-
好的,我知道你在做什么。你想给出不同的消息,取决于
value的类型;这听起来像是一个重载的函数。 -
为什么要使用宏?考虑@Jarod42 建议的函数模板。如果需要,可以向其中添加一个宏来获取封闭的函数名称。但按照惯例,宏应该是
ALL_CAPS_SNAKE_CASE。