C++ 转换向量<;T>;初始化列表<;T>;

C++ 转换向量<;T>;初始化列表<;T>;,c++,c++11,stl,initializer-list,C++,C++11,Stl,Initializer List,每个人都从std::initializer\u list创建std::vector,但反过来呢 例如,如果使用std::initializer\u list作为参数: void someThing(std::initializer_list<int> items) { ... } void someThing(std::initializer\u列表项) { ... } 有时,您将项目放在向量中而不是文字列表中: std::vector<int> v; // popu

每个人都从
std::initializer\u list
创建
std::vector
,但反过来呢

例如,如果使用
std::initializer\u list
作为参数:

void someThing(std::initializer_list<int> items)
{
...
}
void someThing(std::initializer\u列表项)
{
...
}
有时,您将项目放在
向量中而不是文字列表中:

std::vector<int> v;
// populate v with values
someThing(v); // boom! No viable conversion etc.
std::vector<int> v = { 1, 2 };
auto i = { 1, 2 };
someThing(begin(v), end(v)); // OK
someThing(i); // also OK
someThing({1, 2}); // even better
std::vector v;
//用值填充v
某物(v);//繁荣没有可行的转换等。
更一般的问题是:如何从stl表创建
stl::initializer\u list
,而不仅仅是
std::vector

。没有这样的构造函数(我相信有充分的理由),
std::initializer\u list
是一种奇怪的生物


您可以改为将
someThing()
更改为接受一对迭代器。这样,您就可以得到您想要的,只要您可以更改该函数的签名(它不在第三方库中等)。

答案是否定的,您不能这样做

类型为
std::initializer\u list
的对象是一个轻量级代理对象,提供对类型为T的对象数组的访问。在以下情况下,自动构造std::initializer\u list
对象:

  • 带括号的init列表用于列表初始化,包括函数调用列表初始化和赋值表达式(不要与构造函数初始值设定项列表混淆)
  • 大括号的init列表绑定到auto,包括在ranged for循环中
就库支持而言,
std::initializer\u list
只有一个构造空列表的默认构造函数,它的迭代器是常量。缺少
push_-back()
成员意味着您无法使用
std::back_插入器
迭代器适配器来应用例如
std::copy
,也无法通过此类迭代器直接分配:

#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <vector>

int main() 
{
    auto v = std::vector<int> { 1, 2 };
    std::initializer_list<int> i;
    auto it = std::begin(i);
    *it = begin(v); // error: read-only variable is not assignable
}
您应该按照类似的方式修改代码:

void someThing(std::initializer_list<int> items)
{
    someThing(items.begin(), items.end()); // delegate
}

template<class It>
void someThing(It first, It last)
{
    for (auto it = first, it != last; ++it) // do your thing
}
void someThing(std::initializer\u列表项)
{
某物(items.begin(),items.end());//委托
}
模板
使某物作废(先作废,后作废)
{
for(auto it=first,it!=last;++it)//做你自己的事
}
当项目位于向量而不是文本列表中时:

std::vector<int> v;
// populate v with values
someThing(v); // boom! No viable conversion etc.
std::vector<int> v = { 1, 2 };
auto i = { 1, 2 };
someThing(begin(v), end(v)); // OK
someThing(i); // also OK
someThing({1, 2}); // even better
std::vector v={1,2};
自动i={1,2};
某事(开始(v),结束(v));//好啊
某物(我);//也可以
某物({1,2});//更好

是的,你可以这样做,但你不想这样做,因为你必须这样做是非常愚蠢的

首先,确定列表的最大长度。必须有一个最大长度,因为
size\u t
不是无界的。最好找一个更好(更小)的,比如10个

其次,编写接受运行时整数的magic switch代码,并将其映射到编译时整数,然后使用该编译时整数调用模板类或函数。这样的代码需要一个最大整数大小——使用上面的最大长度

现在,神奇地将向量的大小转换为编译时长度

创建整数的编译时序列,从
0
length-1
。每次调用
std::vector
上的
[]
时,在
初始值设定项列表中解压该序列。使用生成的
初始值设定项\u列表
调用函数

上面这句话既狡猾又可笑,大多数编译器都会对此大发雷霆。有一个步骤我不确定它的合法性-
初始值设定项列表的构造是否是进行varardic参数解包的合法场所

下面是一个魔术开关的示例:

以下是索引或序列技巧的示例:

这篇文章应该只是理论上的兴趣,因为实际上这是解决这个问题的一个非常愚蠢的方法


如果不做n^2的功,那么使用任意的iterable则更难。但由于以上已经够可笑的了,而武断的可译版本会更可笑。。。(可能有一包lambda——获取它以便按顺序计算参数可能很棘手。在对初始值设定项列表计算各种参数之间是否存在序列点?)

我发布了一种似乎可行的方法,但不幸的是,由于如何将初始值设定项列表视为对值的本地范围副本的引用,导致了内存访问冲突

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

如果出于某种模糊的原因,您需要解决此问题,并且没有其他选择,您可以尝试此黑客

#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;
}
#包括
#包括
#包括
#包括
#包括
名称空间\uuu范围\u到\u初始值设定项\u列表{
constexpr size\u t DEFAULT\u MAX\u LENGTH=128;
模板结构backingValue{static V value;};
模板V backingValue::value;
模板结构backingList{static std::initializer_list list;};
模板
std::initializer_list backingList::list={(Vcount)backingValue::value…};
模板
静态typename std::enable_如果=maxLength,
std::initializer\u list>::键入generate\u n(开始、结束、当前)
{
抛出std::length_错误(“范围内超过maxLength元素”);
}
模板
静态typename std::如果::键入generate\u n(开始、结束、当前)
{
如果(当前!=结束)
返回生成(开始、结束、+当前);
电流=开始;
for(auto it=backingList::list.begin();
it!=backingList::list.end();
void someThing(std::initializer_list<int> items)
{
     std::vector<int> v;
     for(int i:items)
     {
             v.push_back(i);
     }
     someThing(v);
}

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