避免宏中不可能的情况
avoiding impossible cases in macro
考虑以下宏:
#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;
}
所以我必须使用宏才能离开函数(我不可能使用模板)。
无论输入类型如何,我都通过将 value
转换为 std::string
来解决问题。
#define checkExists(map, it, value) {\
it = map.find(value);\
if(it == map.end()){\
std::stringstream tmpSs;\
if(!(strcmp(typeid(value).name(), "Pc") * strcmp(typeid(value).name(), "PKc") * strcmp(typeid(value).name(), "Ss"))){\
tmpSs << value;\
}else{\
tmpSs << "0x" << std::uppercase << std::setfill('0') << std::setw(4) << std::hex << value; /* converting value to hex format */\
}\
\
manageError(ERRCAN_T_FIND_RESSOURCES, "in %s __ failed to find %s in map %s", __FUNCTION__, tmpSs.str().c_str(), #map);\
}\
}
考虑以下宏:
#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;
}
所以我必须使用宏才能离开函数(我不可能使用模板)。
无论输入类型如何,我都通过将 value
转换为 std::string
来解决问题。
#define checkExists(map, it, value) {\
it = map.find(value);\
if(it == map.end()){\
std::stringstream tmpSs;\
if(!(strcmp(typeid(value).name(), "Pc") * strcmp(typeid(value).name(), "PKc") * strcmp(typeid(value).name(), "Ss"))){\
tmpSs << value;\
}else{\
tmpSs << "0x" << std::uppercase << std::setfill('0') << std::setw(4) << std::hex << value; /* converting value to hex format */\
}\
\
manageError(ERRCAN_T_FIND_RESSOURCES, "in %s __ failed to find %s in map %s", __FUNCTION__, tmpSs.str().c_str(), #map);\
}\
}