Reputation:
I am trying to use a fold expression as the argument of the [] operator. Unfortunately, only the first element is correct.
template <class ...U> T& operator[](U ...indices){
size_t i=0, k[get_n_dimensions()];
(... , void(k[i++]=indices));
// use k[0], k[1], ...
// only k[0] is correct
}
However, if I use the same syntax for the argument of a function, it works fine.
template <class ...U> T get(U ...indices) const {
size_t i=0, k[get_n_dimensions()];
(... , void(k[i++]=indices));
// k[0], k[1], ... filled correctly
}
What is the reason? What would be the solution?
Upvotes: 2
Views: 472
Reputation: 41145
As others have mentioned, the subscripting operator operator[]
must accept only a single parameter.
See [over.sub] (emphasis mine)
operator[]
shall be a non-static member function with exactly one parameter. It implements the subscripting syntax
However, that one parameter doesn't have to be an integer.
You could still do what you want if you are able to move your values into a std::index_sequence
like so:
template<size_t... indices>
T& operator[](std::index_sequence<indices...>){
size_t i=0, k[get_n_dimensions()];
(... , void(k[i++]=indices));
// ...
}
You'd call it like so
my_instance[std::make_index_sequence<3>{}]; // passes 0, 1, 2 to the function
Upvotes: 0
Reputation: 66459
C++ does not have multi-dimensional indexing, and that's "hard-wired" into the syntax - you can't add it by overloading.
The reason that your code compiles at all is that p[a,b]
is equivalent to p[(a,b)]
- that is, it uses the regular comma operator which will compute a
and ignore the result, then produce the value of b
as the index into p
.
Thus, your template is never used "variadically", but is essentially the same as
template <class U> T& operator[](U indices)
You need to name the function, or overload an operator that can take more than one parameter, such as operator()
.
Upvotes: 4
Reputation: 93364
What is the reason?
The array subscript operator (operator[]
) must have exactly one argument. The first snippet you have shown is invalid for any sizeof...(U) != 1
.
A function template like get
or another operator like operator()
do not have a similar limitation.
What would be the solution?
Do not use operator[]
.
Upvotes: 7