0

I decided to implement Python's slice with C++ by myself. I wrote a function which accepts variadic slice_info<int> arguments and returns the slice selection of an n-dimensional array, ndvalarray<T, D>.

I compiled with Visual C++ 2015 and the code is like the following:

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
}

I thought #1 is an error because

braced-init-list is not an expression and therefore has no type

I tried #2 and #3, and they worked. However I am still wondering is there are possible ways to make #1 possible. This question is a bit similar with c11-variable-number-of-arguments-same-specific-type, and in my case these variable number of arguments are braced-init-list.

slice_info<T> accepts a std::initializer_list<T>, in order to describe a slice selection of a dimension, like std::slice(). ndvalarray has more than one dimension, so I have to give a pack of slice_info<T>.

I choose to implement a constructor with a std::initializer_list<T> argument, because I can use a braced-init-list, and I don't need to give T or call constructors explicitly (like #2 does). Maybe it's a bad design, but I think it's simple to use.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
calvin
  • 2,125
  • 2
  • 21
  • 38
  • I delete some code which I thought is irrelevant to my question – calvin Dec 29 '16 at 06:01
  • Braced-init-lists are never deducible as types. If you want #1's call-syntax to work, remove the type deduction from #1. – ildjarn Dec 29 '16 at 06:01
  • @ildjarn do you mean I have to wrote like #2? – calvin Dec 29 '16 at 06:11
  • Sorry, I miswrote and can't edit now. If you want #1's call-syntax to work, remove the type deduction from `slice`. – ildjarn Dec 29 '16 at 06:21
  • @ildjarn the only way I can see to remove type deduction from `slice` is to remove `typename ... Args`, and wrote some overloading functions instead. However I can't pass variable number of arguments then. Is this what you mean, or I misunderstood? – calvin Dec 29 '16 at 07:08
  • Yes, that's what I mean, mostly: if you want a sequence of `slice_info`, then take a pack of `slice_info`, not an unconstrained pack. You _can_ pass a variable number of `slice_info`s... – ildjarn Dec 29 '16 at 07:53
  • @ildjarn how can I take a pack of `slice_info` instead of an unconstrained pack? Do I need some SFINAE thing, or like top votes on [c11-variable-number-of-arguments-same-specific-type](http://stackoverflow.com/questions/18017543/c11-variable-number-of-arguments-same-specific-type), I can use `std::initializer_list` or some other containers(like my #3 does)? – calvin Dec 29 '16 at 08:55
  • Apologies, now that I see your problem more clearly I'll have to retract my earlier statement: you can pass a variable number of `slice_info`s, but not with the syntax you're looking for. [This](http://coliru.stacked-crooked.com/a/bba1e4623345c32e) isn't too far off and might work for you, though. – ildjarn Jan 04 '17 at 20:31
  • @ildjarn I thought this is what I want, thank you – calvin Jan 06 '17 at 12:48

0 Answers0