是否可以使用 C++0x initializer_list 实现类似 std::array 的容器(内置 C 数组的薄包装器)?
是的,好吧,只要你愿意作弊。正如 Mooing Duck 指出的那样,不,甚至不作弊,除非编译器实现者允许。尽管如此,仍然可以足够接近——可以使用初始化列表和被包装器隐藏的静态数组。
这是我为我的个人工具箱编写的一些代码。关键是完全忽略大小,即使是数组,让提供者容器处理它;在这种情况下,initializer_list
谁可以通过 提供大小std::distance
,从而避免客户端大小显式化(似乎是我刚刚发明的一个术语)。
由于它是“任何人都可以想出”的代码,因此将其“返回”给公众没有问题;事实上,我从某个专家那里得到了这个想法,我不记得他在 Freenode 的##c++
频道上的昵称,所以我想这是对他们的认可:
*编辑*编:
template <typename T> struct carray {
// typedefs for iterator. The best seems to be to use std::iterator<std::random_iterator_tag,T,int> here
...
template <size_t N>
explicit carray (T (&arr)[N])
: ax(arr), sx(N) {}
// note the linked article.
// This works *only* if the compiler implementor lets you.
carray (std::initializer_list<T> X)
: ax (X.begin()), sx(std::distance(X.begin(),X.end()) {}
// YMMV about the rest of the "rule of N":
// no copy constructor needed -- trivial
// no destructor needed -- data outscopes the wrapper
// no assignment operator needed -- trivial
// container functions, like begin(), end(), size()...
private:
T* ax;
size_t const sx;
};
C++0x 模式下的使用和声明非常简单(刚刚在 Fedora 15 中使用 GCC 4.6 进行了测试),但它适用于上面外部链接中提到的警告,因此它显然是未定义的行为:
using lpp::carray;
carray<short const> CS = {1, -7, 4, 188};
但是,我不明白为什么编译器实现者无论如何都不会将积分的 initializer_list 实现为静态数组。你的来电。
不仅如此,只要你可以#ifdef
在 pre-C++0x 模式下使用初始化构造器,你实际上可以在 pre-C++0x 中使用它;尽管需要将数据数组预先声明为其自己的变量,但恕我直言,它最接近原始意图(并且它具有可用且不会导致例如:范围问题的优点)。(也用上面的编译器测试过,加上 Debian Wheezy 的 GCC):
using lpp::carray;
short data[]= {1, -7, 4, 188};
carray<short const> CS (data);
那里!任何地方都没有“大小”参数!
如果没有提供初始化列表,我们还想提供一个构造函数来指定大小。
抱歉,这是我尚未实施的一项功能。问题是如何从外部源(可能是分配器)“静态”分配内存。假设它可以通过辅助函子以某种方式完成allocate
,那么构造函数将是这样的:
explicit carray (size_t N)
: ax(allocate(N)), sx(N) {}
我希望这段代码有帮助,因为我看到这个问题或多或少是旧的。