避免宏中不可能的情况

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 的宏,它只接受基本类型(例如 intchar* ...)。原型是:

#define manageError(error_code, error_str, ...) {\
    {\
        logWarning(error_str, ##__VA_ARGS__);\
        return error_code;\
    }\
}

int logWarning(const char* printf_format, ...);

所以如果我的 valuestd::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);\
    }\
}