我曾发布过一种看起来可行的方法,但由于initializer_lists被视为对本地作用域值的引用而导致内存访问违规,所以不幸地失败了。
这里有一个替代方案。针对每个可能的项数,使用参数包进行计数,生成一个单独的函数和一个单独的静态初始化列表。这不是线程安全的,并且使用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;
}
foo({1,2,3})
能够正常工作,但是int f[] = {1,2,3}; foo(f);
却不能;而且需要传递双迭代器,这正是我想要避免的,因为 std::initializer_list 如此巧妙地将两者包装成一个。至少,我希望有一个 std::initializer_list 构造函数可以接受一个 const 静态数组。 - Dwayne Robinsonvector
作为临时对象的方法,并且我想从中创建一个set
。如果我可以写成set<Type> foo{initializer_list<Type>(getVector())};
(或类似的东西),那就可以了。我不能写成set<Type> foo(getVector.begin(), getVector().end());
(返回值没有被存储,而是在调用期间计算)。所以我需要将向量复制到本地对象中,并使用该对象进行迭代器。这是额外的移动构造和更多的代码行,以及意外引用的额外变量。 - Troy Daniels