-3

我需要知道对于所有编译器是否可以保证&N == &N_neg[MAXN]以下代码中的这一点。

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

如果是这样,我就完成了,这就是我所需要的。如果没有,请阅读下面的完整问题。

注意:这仅适用于编程竞赛因此不必担心可维护性。我更关心保持T易于理解。


我有以下定义:

template<int* B> class T { ... }

但是,在里面T,我访问B[-n], where n > 0。所以,这就是我想要做的:

#define MAXN 1000
int N[2*MAXN];
T<N + MAXN> t;

根据编译器,这是不允许的。cppreference甚至有一个关于这种特殊情况的例子,说它不起作用,我已经在其他地方搜索了解决方案(还没有找到)。我确实了解模板是如何工作的,并且我知道(以及为什么)每个模板参数的值必须在编译期间知道,并且N只有在链接期间才知道的地址。

有什么建议么?


这是完整的代码(以防有人根据问题提出任何建议):

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;
    }
};
4

1 回答 1

2

如果可以保证,对于所有编译器,&N == &N_neg[MAXN]

绝对不能保证。C++ 标准不要求变量的相对内存布局。事实上,它对内存布局的一般限制很少。

从技术上讲,它甚至不能保证,N并且N_neg在某些情况下不会被编译器优化掉(尽管获取它们的地址通常会防止这种情况发生)。


要使布局顺序,您可以使用结构:

struct { int N_neg[MAXN], N[MAXN]; } arrays;

然后,理论上您可以访问N_neg[MAXN]N[0]. 但是,这是未定义的行为!可以为您工作,但假设您分配给N_neg[MAXN]. 编译器可能会假设它不能N[0]被修改,并优化对它的任何访问,导致你的程序行为异常。

你可以通过声明两个数组来在一定程度上解决这个问题volatile,但是你会失去大量潜在的优化。

因此,我会非常不愿意使用这种方法。坚持既定的行为几乎总是更好。


根据更新/发现的要求,这使您几乎只需要一个模板参数:

template <typename T, T&>
struct Hash;

template <std::size_t Size, typename T, T (&Array)[Size]>
struct Hash<T[Size], Array>
{
    // Your code here

private:
    static constexpr T *N = &Array[Size / 2];
};

像这样实例化:

int N_backing[MAXN * 2];
Hash<decltype(N_backing), N_backing> hash;

照原样,Nconstexpr的值保证在编译时计算。

于 2017-09-18T19:01:00.813 回答