I need to know if it is guaranteed, for all compilers, that &N == &N_neg[MAXN] in the following code.
int N_neg[MAXN], N[MAXN]; // defined in the global scope!
T<N> t; // so I can access N[i] (for i < 0) inside T
If so, I'm done, this is all I need. If not, please read my full problem below.
NOTE: This is meant for programming contests only, so don't worry about maintainability. I'm more concerned about keeping T easy to understand.
I have the following definition:
template<int* B> class T { ... }
Inside T, however, I access B[-n], where n > 0. So, this is what I want to do:
#define MAXN 1000
int N[2*MAXN];
T<N + MAXN> t;
This is not allowed, according to the compiler. cppreference even has an example of this particular case saying it does not work, and I have already searched everywhere else for a solution (none to be found yet). I do understand how templates work, and I do know that (and why) the value of each template argument must be known during compilation time, and the address of N is only known later during linking.
Any suggestions?
Here is the full code (just in case someone has any suggestion based on the problem):
template<int M, int B[]> struct Hash {
int h; Hash(int h = 0): h(h) {}
int disp(int i) { return B[i]; }
Hash concat(int ch, int i) { return (h + (ll) ch * B[i]) % M; }
Hash subtract(int hl, int i) { return (ll) (h - hl + M) * B[-i] % M; }
static void genBase(int n, int b) {
B[0] = 1, B[-1] = powlg(b, M-2, M); // b^(-1) % M = b^(M-2) % M
for (int i = 1; i < n; i++)
B[i] = (ll) B[i-1] * b % M, B[-i] = (ll)B[-i+1] * B[-1] % M;
}
};
It is absolutely not guaranteed. The C++ standard does not mandate the relative memory layout of variables. In fact, it places very little restrictions on memory layout in general.
It's technically not even guaranteed that
NandN_negwon't be optimized away by the compiler in some cases (though taking their addresses will generally prevent this from happening).To make the layout sequential, you can use a struct:
Then, in theory you can access
N_neg[MAXN]as the same memory location asN[0]. However, this is undefined behavior! It could work for you, but let's say you assign toN_neg[MAXN]. The compiler may assume thatN[0]couldn't've been modified, and optimize away any accesses to it, causing your program to behave strangely.You can get around this to some degree by declaring both arrays
volatile, but then you lose out on a ton of potential optimizations.Therefore, I would be very reluctant to use this approach. It's almost always better to stick to defined behavior.
Based on the updated/discovered requirements, this gets you close to needing only one template parameter:
Instantiated like this:
As
Nisconstexpr, its value is guaranteed to be computed at compile time.