简体   繁体   English

有没有办法从未知数量的 arguments 构造一个 std::initializer_list ?

[英]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:注意事项:

  • The max number of elements you aim to support must be known at compile time.您要支持的最大元素数必须在编译时知道。
  • It's terribly slow to compile.编译速度非常慢。
  • It instantiates a function template 1½ times the number of elements in the initializer_list<T> you aim to support.它实例化一个 function 模板,该模板是您希望支持的initializer_list<T>中元素数量的 1½ 倍。
  • It uses a binary search to find the correct overload in run-time.它使用二进制搜索在运行时找到正确的重载。 This is pretty quick though.不过这很快。

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.

相关问题 有没有办法在编译时检查std :: initializer_list参数的数量? - Is there a way to check std::initializer_list number of arguments at compile-time? 是否可以以编程方式构造std :: initializer_list? - Is it possible to programmatically construct a std::initializer_list? 有没有办法 append 初始化列表 --&gt; std::initializer_list <std::pair<std::string, std::string> &gt;? </std::pair<std::string,> - Is there any way to append initializer list --> std::initializer_list<std::pair<std::string, std::string>>? 有没有办法在编译时从 initializer_list 构造? - Is there way to construct from initializer_list in compile time? 从 std::array 私有继承时无法从 std::initializer_list 构造 - Can't construct from std::initializer_list when privately inheriting from std::array 无法从std :: initializer_list <int>构造std :: initializer_list <int const> - std::initializer_list<int const> cannot be constructed from std::initializer_list<int> 我们不能从initializer_list创建std :: array,但是可以使用带有可变参数的辅助函数来创建它吗? - We cannot create an std::array from an initializer_list, but can we create it with a helper function with variadic arguments? 在Ctor调用中将std :: initializer_list与括号内的参数分开 - Separating std::initializer_list from parenthesis-enclosed arguments in Ctor invocation std :: initializer_list构造函数 - std::initializer_list constructor std :: initializer_list的实现 - the implemention of std::initializer_list
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM