将 vector<T> 转换为 initializer_list<T>

新手上路,请多包涵

每个人都从 std::initializer_list 创建 std::vector --- ,但是反过来呢?

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

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

有时您将项目放在 vector<T> 而不是文字列表中:

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

更普遍的问题是:如何从 STL 可迭代对象中创建 stl::initializer_list ,而不仅仅是 std::vector

原文由 Fil 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.6k
2 个回答

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

这是一个替代方案。为每个可能的项目数生成一个单独的函数和一个单独的静态初始化器列表,这些项目使用参数包进行计数。这不是线程安全的,并且使用 const_cast(这被认为非常糟糕)写入静态 initializer_list 内存。但是,它在 gcc 和 clang 中都能正常工作。

如果由于某种不明原因您需要解决此问题并且没有其他选择,您可以尝试这个 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;
}

原文由 fuzzyTew 发布,翻译遵循 CC BY-SA 3.0 许可协议

std::vector<int> v;
someThing(std::initializer_list<int>(&v.front(), &v.front() + v.size()));

原文由 Stackoverflow 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题