[英]Is there any way to construct an std::initializer_list from an unknown number of arguments?
Hi there so im having some trouble battling a silly API.嗨,所以我在与愚蠢的 API 作斗争时遇到了一些麻烦。 We have a function that is something along the lines of
我们有一个 function 类似于
void foo(std::initializer_list<T> access_list);
And what I want to do is take a run-time JSON array and use it to call this function.我想做的是获取一个运行时 JSON 数组并用它来调用这个 function。 for example suppose the JSON was
例如假设 JSON 是
data : [
{
x : 10,
y : 20
},
{
x : 30,
y : 40
},
...
]
Then id want to call foo
with foo({10,20,30,40})
.然后 id 想用
foo({10,20,30,40})
调用foo
。
The problem is, the JSON array can be any length so id have to construct the list in a loop (ie into a vector) and then call foo
on the constructed list.问题是,JSON 数组可以是任意长度,因此 id 必须在循环中构造列表(即到向量中),然后在构造的列表上调用
foo
。 This is not possible as std::initializer_list does not have any functions to modify it after its initialisation and has no way of converting from a container (such as vector/array etc.) to an std::initializer_list.这是不可能的,因为 std::initializer_list 在其初始化后没有任何修改它的函数,并且无法从容器(例如向量/数组等)转换为 std::initializer_list。
I understand this is a misuse of std::initializer_list but is there any way (macros welcome) to create such a list?我知道这是对 std::initializer_list 的滥用,但是有什么方法(欢迎使用宏)来创建这样的列表吗?
I think one approach might be to convert the std::vector into a parameter pack and then a macro on the parameter pack to form the std::initializer_list but im not exactly sure how that would look.我认为一种方法可能是将 std::vector 转换为参数包,然后将参数包上的宏转换为 std::initializer_list 但我不确定它的外观。 Thanks:).
谢谢:)。
If you are stuck with void foo(std::initializer_list<T> access_list);
如果您遇到
void foo(std::initializer_list<T> access_list);
and you've populated a vector<T>
with the data you'd like to supply to foo<T>
, then you could build a runtime translator.并且您已经使用要提供给
foo<T>
的数据填充了vector<T>
> ,然后您可以构建一个运行时翻译器。
Caveats:注意事项:
initializer_list<T>
you aim to support.initializer_list<T>
中元素数量的 1½ 倍。 If you aim to support relatively few elements (I use 512 in my example) you may be able to live with this.如果您的目标是支持相对较少的元素(我在示例中使用 512),您可能可以忍受这一点。
namespace detail {
template<class Func, class T, size_t... Is>
decltype(auto) helper(Func&& f, const std::vector<T>& vec,
std::index_sequence<Is...>)
{
if constexpr(sizeof...(Is) > 512) { // will throw a runtime exception
throw std::runtime_error("more than 512 elements not supported");
} else {
if(sizeof...(Is) + 255 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 256>{});
if(sizeof...(Is) + 127 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 128>{});
if(sizeof...(Is) + 63 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 64>{});
if(sizeof...(Is) + 31 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 32>{});
if(sizeof...(Is) + 15 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 16>{});
if(sizeof...(Is) + 7 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 8>{});
if(sizeof...(Is) + 3 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 4>{});
if(sizeof...(Is) + 1 < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 2>{});
if(sizeof...(Is) < vec.size())
return helper(std::forward<Func>(f), vec,
std::make_index_sequence<sizeof...(Is) + 1>{});
// time to do the actual call:
return f({vec[Is]...});
}
}
} // namespace detail
template<class Func, class T>
decltype(auto) call(Func&& f, const std::vector<T>& vec) {
return detail::helper(std::forward<Func>(f), vec,
std::make_index_sequence<0>{});
}
You'd then call foo<T>
like so:然后你会像这样调用
foo<T>
:
std::vector<T> vec = ...;
call(foo<T>, vec);
Demo - likely to time out during compilation - but works if you don't have such a limit.演示- 可能在编译期间超时 - 但如果您没有这样的限制,则可以使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.