假设我有一个模板函数,它可以推断出数组参数的长度。
如果我像这样调用,一切都很好:
大多数端点至少需要一个参数,但许多端点不需要参数。看起来这确实是GCC和clang都实现的扩展(但似乎并不完全……)。我可以想到几个解决方法:
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都实现的扩展(但似乎并不完全……)。我可以想到几个解决方法:
重载
api_endpoint
构造函数以特殊处理零长度参数(但我需要23个来覆盖每个可零长度参数),这是GCC / clang扩展可以接受的。不要尝试推断数组长度,将其作为单独的参数(并继续使用零长度数组)
对于这些参数,使用更高级别的数据结构,如向量
使用魔术值表示“空”
...但如果有更好的想法,我很乐意听取。
std::vector
。 - Puppystd::array
和boost::array
也支持长度为零。 - Johannes Schaub - litb