xyl*_*per 4 c++ arrays initializer-list c++11
我可以通过{1, 2, 3}两种方式编写一个以临时数组(例如)作为参数的函数:
// using array
template<typename T, int N>
auto foo1(const T(&t)[N]) -> void;
// using std::initializer_list
template<typename T>
auto foo2(std::initializer_list<T> t) -> void;
Run Code Online (Sandbox Code Playgroud)
是否有任何准则可以告诉哪一个更好?
他们都是截然不同的东西。还有2或3个其他合理的选择。
template<class T, std::size_t N>
void foo_a( std::array<T, N> const& );
template<class T>
void foo_b( gsl::span<const T> );
template<class T, std::size_t N >
void foo_c( T const(&)[N] );
template<class T>
void foo_d( std::initializer_list<T> );
template<class T, class A=std::allocator<T> >
void foo_e( std::vector<T, A> const& );
template<class...Ts>
void foo_f( std::tuple<Ts...> const& );
template<class...Ts>
void foo_g( Ts const& ... );
Run Code Online (Sandbox Code Playgroud)
这里有6种不同的方法来计算一堆Ts。
它们相互之间都有优点和缺点。
最接近严格的foo_a结束了foo_c; foo_c唯一的好处是它与C样式数组更兼容。
foo_b让您可以消费除之外的任何其他商品foo_f。很好。
a,c和f都具有在时确定的编译时长度foo。这可能会有所不同,具体取决于您在做什么。从理论上讲,您可以编写foo_b处理固定长度的类型视图,但是没有人打扰。
e是唯一在呼叫站点支持动态长度的服务器。
f支持不同的类型,但使迭代过程不太干净。
所有这些都可以稍作修改以允许移出(即使初始化列表列出了更多样板)。
d给出最简单的值{},但是g同样干净({}完全省略)。
通常,我会使用我的主页gsl::span版本。它有一个initializer_list构造函数。而且我非常很少想要推断T。