I don't know a general solution but you can solve your specific problem (use the first, or the second or the third index or...) using a reference.
In the 3D case, first you can declare the loop variables (i
, j
and k
)
std::size_t i, j, k;
Next you can "link" another variable (r
) to i
, j
or k
according to a template value I
std::size_t & r = (I == 0U ? i : (I == 1U ? j : k));
The following is a compilable example
#include <vector>
#include <iostream>
template <std::size_t I>
void func (std::vector<std::vector<std::vector<double> > > & d)
{
std::size_t i, j, k;
std::size_t & r = (I == 0U ? i : (I == 1U ? j : k));
for ( i = 0U ; i < d.size() ; ++i )
for ( j = 0U ; j < d[i].size() ; ++j )
for ( k = 0U ; k < d[i][j].size() ; ++k )
d[i][j][k] += r+1;
}
int main()
{
std::vector<std::vector<std::vector<double> > > data;
// some data in data
func<0>(data); // r is i
func<1>(data); // r is j
func<2>(data); // r is k
}
--- EDIT ---
The OP ask
is there anyway that this function could work for arbitrary dimension?
No.
Not this function.
But I propose a completely different (and more complex) solution. I write it but don't ask me to check if it really works.
The idea isn't based on reference anymore but on template specialization.
This time the template index is 1-based: use template value 1
if you want intercept the first index (ex x
), 2
if you want intercept the second index (ex y
), etc.
So you call
foo<1U>(data1); // r is the first index
for a 1D vector,
foo<1U>(data2); // r is the first index
foo<2U>(data2); // r is the second index
for a 2D vector, etc.
If you call
foo<I>(data)
where I
is bigger than the dimension of data
, you get a compilation error.
If you call
foo<0>(data)
you get a compilation error but only if you compile C++11 or newer (with C++98 r
become zero; but you can add an assert()
to get a runtime error).
The example
#include <vector>
#include <iostream>
template <std::size_t I>
struct bar
{
template <typename T>
static void baz (std::vector<T> & v, std::size_t)
{
for ( std::size_t i = 0U ; i < v.size() ; ++i )
bar<I-1U>::baz(v[i], i);
}
};
template <>
struct bar<0U>
{
template <typename T>
static void baz (std::vector<T> & v, std::size_t r)
{
for ( std::size_t i = 0U ; i < v.size() ; ++i )
baz(v[i], r);
}
static void baz (double & d, std::size_t r)
{ d += r + 1U; }
};
template <std::size_t I, typename V>
void foo (V & v)
{
#if __cplusplus >= 201103L
static_assert(I > 0U, "!"); // c++11 or newer
#endif
bar<I>::baz(v, 0U);
}
int main()
{
std::vector<double > data1;
std::vector<std::vector<double> > data2;
std::vector<std::vector<std::vector<double> > > data3;
// some data in data1, data2 and data3
// foo<0U>(data1); // compilation error in C++11 or newer
foo<1U>(data1); // r is the first index
// foo<2U>(data1); // compilation error
// foo<0U>(data2); // compilation error in C++11 or newer
foo<1U>(data2); // r is the first index
foo<2U>(data2); // r is the second index
// foo<3U>(data2); // compilation error
// foo<0U>(data3); // compilation error in C++11 or newer
foo<1U>(data3); // r is the first index
foo<2U>(data3); // r is the second index
foo<3U>(data3); // r is the third index
// foo<4U>(data3); // compilation error
}