我决定自己用C ++实现Python的切片。我编写了一个函数,它接受可变参数slice_info<int>
并返回n维数组的切片选择ndvalarray<T, D>
。
我使用Visual C ++ 2015编译,代码如下:
template<typename T>
struct slice_info {
T fr, to, step;
slice_info(T i) {
fr = 1; to = i; step = 1;
}
slice_info(std::initializer_list<T> il) {
std::vector<T> l(il);
if (l.size() == 1)
{
fr = 1; step = 1; to = l[0];
}
else if (l.size() == 2) {
fr = l[0]; step = 1; to = l[1];
}
else {
fr = l[0]; step = l[2]; to = l[1];
}
}
slice_info(const slice_info<T> & x) : fr(x.fr), to(x.to), step(x.step) {
}
};
template<typename T, int D>
void slice(const ndvalarray<T, D> & va, slice_info<int>&& s) {
// ndvalarray<T, D> is a n-dimensional array of type T
}
template<typename T, int D, typename ... Args>
void slice(const ndvalarray<T, D> & va, slice_info<int>&& s, Args&& ... args) {
slice(va, std::forward<Args>(args)...);
}
template<typename T, int D>
void slice_work_around(const ndvalarray<T, D> & va, const std::vector<slice_info<int>> & vs) {
}
int main(){
// Here is a 3-dimensional arr
ndvalarray<int, 3> arr;
// I want to get a slice copy of arr.
// For dimension 1, I select elements from position 1 to position 2.
// For dimension 2, I select elements from position 3 to position 6 stride 2
// For dimension 3, I select only the position 7 element
slice(arr, { 1, 2 }, { 3, 6, 2 }, {7}); // #1 error
slice(arr, { 1, 2 }, slice_info<int>{ 3, 6, 2 }, slice_info<int>{7}); // #2 yes
slice_work_around(arr, { {1, 2}, {3, 6, 2}, {7} }); // #3 yes
}
我认为#1是错误的,因为
braced-init-list不是表达式,因此没有类型
我尝试了#2和#3,他们工作了。但是我仍然想知道是否有可能使#1成为可能的方法。这个问题与c11-variable-number-of-arguments-same-specific-type有点类似,在我的例子中,这些可变数量的参数是braced-init-list。
slice_info<T>
接受std::initializer_list<T>
,以便描述维度的切片选择,例如std::slice()
。 ndvalarray
有多个维度,因此我必须提供一包slice_info<T>
。
我选择使用std::initializer_list<T>
参数实现构造函数,因为我可以使用braced-init-list,而不需要给T
或显式调用构造函数(比如#2)一样)。也许这是一个糟糕的设计,但我认为使用起来很简单。