转换向量< T>到initializer_list< T> [英] Convert a vector<T> to initializer_list<T>

查看:91
本文介绍了转换向量< T>到initializer_list< T>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每个人都从 std :: initializer_list 创建 std :: vector ,但是相反吗?

Everyone creates std::vector from std::initializer_list, but what about the other way around?

例如。如果您使用 std :: initializer_list 作为参数:

eg. if you use a std::initializer_list as a parameter:

void someThing(std::initializer_list<int> items)
{
...
}

有时候,您将商品放在 vector< T> 而不是文字列表中:

There are times when you have your items in a vector<T> instead of a literal list:

std::vector<int> v;
// populate v with values
someThing(v); // boom! No viable conversion etc.

更普遍的问题是:如何创建来自STL迭代的stl :: initializer_list ,而不仅仅是 std :: vector

The more general question is: how to create an stl::initializer_list from a STL iterable, not just std::vector.

推荐答案

我发布了一种似乎可行的方法,但不幸的是,由于将initializer_lists视为对本地作用域值副本的引用,导致了内存访问冲突。

I posted a way that seemed to work but unfortunately caused memory access violations because of how initializer_lists are treated as references to locally-scoped copies of values.

这里是另一种选择。将为每个可能的项目数量生成一个单独的函数和一个单独的静态初始化程序列表,这些数量将通过参数包进行计数。这不是线程安全的,并使用const_cast(被认为是非常糟糕的)写入静态initializer_list内存中。但是,它在gcc和clang中都可以正常工作。

Here's an alternative. A separate function and a separate static initializer list is generated for each possible number of items, which are counted with a parameter pack. This is not thread safe and uses a const_cast (which is considered very bad) to write into the static initializer_list memory. However, it works cleanly in both gcc and clang.

如果出于某种晦涩的原因,您需要解决此问题并且没有其他选择,则可以尝试这种方法。

If for some obscure reason you need this problem solved and have no other options, you could try this hack.

#include <initializer_list>
#include <iostream>
#include <stdexcept>
#include <type_traits>
#include <vector>

namespace __range_to_initializer_list {

    constexpr size_t DEFAULT_MAX_LENGTH = 128;

    template <typename V> struct backingValue { static V value; };
    template <typename V> V backingValue<V>::value;

    template <typename V, typename... Vcount> struct backingList { static std::initializer_list<V> list; };
    template <typename V, typename... Vcount>
    std::initializer_list<V> backingList<V, Vcount...>::list = {(Vcount)backingValue<V>::value...};

    template <size_t maxLength, typename It, typename V = typename It::value_type, typename... Vcount>
    static typename std::enable_if< sizeof...(Vcount) >= maxLength,
    std::initializer_list<V> >::type generate_n(It begin, It end, It current)
    {
        throw std::length_error("More than maxLength elements in range.");
    }

    template <size_t maxLength = DEFAULT_MAX_LENGTH, typename It, typename V = typename It::value_type, typename... Vcount>
    static typename std::enable_if< sizeof...(Vcount) < maxLength,
    std::initializer_list<V> >::type generate_n(It begin, It end, It current)
    {
        if (current != end)
            return generate_n<maxLength, It, V, V, Vcount...>(begin, end, ++current);

        current = begin;
        for (auto it = backingList<V,Vcount...>::list.begin();
             it != backingList<V,Vcount...>::list.end();
             ++current, ++it)
            *const_cast<V*>(&*it) = *current;

        return backingList<V,Vcount...>::list;
    }

}

template <typename It>
std::initializer_list<typename It::value_type> range_to_initializer_list(It begin, It end)
{
    return __range_to_initializer_list::generate_n(begin, end, begin);
}

int main()
{
    std::vector<int> vec = {1,2,3,4,5,6,7,8,9,10};
    std::initializer_list<int> list = range_to_initializer_list(vec.begin(), vec.end());
    for (int i : list)
        std::cout << i << std::endl;
    return 0;
}

这篇关于转换向量&lt; T&gt;到initializer_list&lt; T&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆