我发布了一种似乎可行的方法,但不幸的是,由于 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;
}