Текущий проект стандарта (и предположительно С++ 17) говорит в [basic.compound/4]:
[Примечание. Объект массива и его первый элемент не являются взаимопереключателями, хотя они имеют одинаковый адрес. - конечная нота]
Таким образом, указатель на объект не может быть reinterpret_cast
'd, чтобы получить свой встроенный указатель на массив.
Теперь, std::launder
washder, [ptr.launder/1]:
template<class T> [[nodiscard]] constexpr T* launder(T* p) noexcept
;Требует:
p
представляет адрес A байта в памяти. Объект X, который находится в пределах его времени жизни и тип которого аналогичен T, расположен по адресу A. Все байты хранения, которые могут быть достигнуты через результат, достижимы черезp
(см. Ниже).
И определение достижимости находится в [ptr.launder/3]:
Замечания: вызов этой функции может использоваться в основном постоянном выражении всякий раз, когда значение его аргумента может использоваться в выражении постоянной константы. Байт памяти доступен по значению указателя, указывающему на объект Y, если он находится в хранилище, занятом Y, объектом, который является взаимно конвертируемым с Y, или непосредственно окружающим объектом массива, если Y является элементом массива. Программа плохо сформирована, если T - тип функции или cv void.
Теперь, на первый взгляд, кажется, что std::launder
можно использовать для выполнения вышеупомянутого преобразования из-за той части, которую я сделал акцент.
Но. Если p
указывает на объект массива, байты массива достижимы в соответствии с этим определением (даже если p
не является взаимно конвертируемым с указателем на указатель), как и результат стирания. Таким образом, кажется, что в определении ничего не говорится об этой проблеме.
Таким образом, можно ли std::launder
использовать для преобразования указателя объекта в свой указатель на массив?