数组vs std :: initializer_list作为函数参数

时间:2018-07-16 01:59:08

标签: c++ arrays c++11 initializer-list

我可以编写一种以两种方式将临时数组(例如{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;

是否有任何指南可以告诉哪一个更好?

1 个答案:

答案 0 :(得分:4)

它们都是截然不同的东西。还有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& ... );

这里有6种不同的方法来拍摄T

它们相互之间都有优点和缺点。

严格严格意义上最接近的是foo_afoo_cfoo_c的优点仅在于它与C样式的数组更兼容。

foo_b使您可以使用foo_f以外的其他任何对象。太好了。

a,c和f都具有foo内的编译时确定的长度。这可能会有所不同,具体取决于您在做什么。从理论上讲,您可以编写一个foo_b类型的视图来处理固定长度,但是没有人打扰。

e是唯一在呼叫站点支持动态长度的服务器。

f支持不同的类型,但是使迭代的过程变得不太干净。

所有这些元素都可以稍作修改以允许移出(甚至是初始化列表列出了更多样板)。

d给出最简单的{},但是g同样干净(完全省略{})。

通常,我会使用我的家庭版gsl::span。它具有initializer_list构造函数。而且我很少想推论T