假设我有一个模板函数来推断数组参数的长度。
template <size_t S>
void join(const char d[], const char *(&arr)[S]) { }
如果我这样称呼它,一切都很好:
const char *messages[] = {
"OK",
"Not OK",
"File not found"
};
join("\n", messages);
但是如果我用一个空数组调用它,像这样:
const char *messages[] = { };
join("\n", messages);
…它不能编译(使用 clang 4.0):
targs.cpp:9:5: 错误:没有匹配的函数调用“加入” 加入(“\n”,消息); ^~~~ targs.cpp:4:6: 注意:候选模板被忽略:替换失败 [with S = 0] 无效连接(常量字符 d[],常量字符 *(&arr)[S]) { } ^ 产生 1 个错误。
我猜它与不喜欢零长度数组的 C++ 有关,但如果函数不是模板并将长度作为单独的参数,它不会抱怨我将消息声明为零长度大批。
这是怎么回事,有什么好的解决方法吗?
我的实际用例是定义 HTTP API 端点采用的参数,看起来像这样:
const api_param_t params[] = {
{ API_TYPE_STRING, "foo" },
{ API_TYPE_UINT64, "bar" },
{ API_TYPE_STRING, "baz" }
}
const api_status_t status_codes[] = { … };
const api_middleware_t middleware[] = { … };
new api_endpoint("/foo", params, status_codes, middleware);
大多数端点至少采用一个参数,但许多端点不采用。看起来这确实是 GCC 和 clang 都实现的扩展(但是,看起来并不完全……)。我可以想到一些解决方法:
将构造函数重载
api_endpoint
到特殊情况的零长度参数(但我需要其中的 2 3个来覆盖每个零长度参数),GCC/clang 扩展可以使用。不要试图推断数组长度,将其作为单独的参数(并继续使用零长度数组)
对这些参数使用更高级别的数据结构,例如向量
使用魔法值来表示“空”
…但如果有人有更好的想法,我很想听听他们