假设我有一个模板函数,它可以推断数组参数的长度。
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: error: no matching function for call to 'join'
join("\n", messages);
^~~~
targs.cpp:4:6: note: candidate template ignored: substitution failure [with S = 0]
void join(const char d[], const char *(&arr;)[S]) { }
^
1 error generated.
我猜测这与 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 都实现的扩展(但是,看起来并不完全......)。我可以想到一些解决方法:
Overload the api_endpoint
constructor to special case zero-length arguments (but I need 23 of them to cover each zero-length-able parameter), which the GCC/clang extension is OK with.
不要尝试推断数组长度,将其作为单独的参数(并继续使用零长度数组)
对这些参数使用更高级别的数据结构(例如向量)
使用魔法值来表示“空”
…但如果有人有更好的想法,我很想听听