У меня есть указатель T * pValues
что я хотел бы рассматривать как T (&values)[N]
В этом так ответ https://stackoverflow.com/a/2634994/239916, предлагаемый способ сделать это
T (&values)[N] = *static_cast<T(*)[N]>(static_cast<void*>(pValues));
Я беспокоюсь об этом. В его примере pValues
инициализируется следующим образом
T theValues[N];
T * pValues = theValues;
Мой вопрос, является ли приведенная конструкция законной, если pValues
происходит от любой из следующих конструкций:
T theValues[N + M]; // M > 0
T * pValues = theValues;
T * pValues = new T[N + M]; // M >= 0
Краткий ответ: вы правы. Актерский состав безопасен, только если pValues
имеет тип T[N]
и оба упомянутых вами случая (другой размер, динамически размещаемый массив), скорее всего, приведут к неопределенное поведение.
Хорошая вещь о static_cast
заключается в том, что некоторые дополнительные проверки выполняются во время компиляции, поэтому, если вам кажется, что вы делаете что-то не так, компилятор будет жаловаться на это (по сравнению с уродливым приведением в стиле C, которое позволяет вам делать почти все), например:
struct A { int i; };
struct C { double d; };
int main() {
A a;
// C* c = (C*) &a; // possible to compile, but leads to undefined behavior
C* c = static_cast<C*>(&a);
}
дам тебе: invalid static_cast from type ‘A*’ to type ‘C*’
В этом случае вы приведете к void*
что с точки зрения проверок, которые могут быть сделаны во время компиляции, является законным почти для всего, и наоборот: void*
может быть возвращено почти ко всему, что делает использование static_cast
совершенно бесполезен в первую очередь, так как эти проверки становятся бесполезными.
Для предыдущего примера:
C* c = static_cast<C*>(static_cast<void*>(&a));
не лучше чем:
C* c = (C*) &a;
и, скорее всего, приведет к неправильному использованию этого указателя и неопределенное поведение с этим.
Другими словами:
A arr[N];
A (&ref)[N] = *static_cast<A(*)[N]>(&arr);
это безопасно и просто отлично. Но как только вы начинаете злоупотреблять static_cast<void*>
нет никаких гарантий относительно того, что на самом деле произойдет, потому что даже такие вещи, как:
C *pC = new C;
A (&ref2)[N] = *static_cast<A(*)[N]>(static_cast<void*>(&pC));
становится возможным.
Других решений пока нет …