Проблема
Ключевое слово restrict
в C отсутствует в С++, поэтому из интереса я искал способ эмуляции одной и той же функции на С++.
В частности, я хотел бы, чтобы следующее было эквивалентным:
// C
void func(S *restrict a, S *restrict b)
// C++
void func(noalias<S, 1> a, noalias<S, 2> b)
где noalias<T, n>
- ведет себя так же, как
T*
при доступе с помощью->
и*
- может быть построено из
T*
(так что эту функцию можно вызывать какfunc(t1, t2)
, гдеt1
иt2
- оба типаT*
) - индекс
n
указывает "класс псевдонимов" переменной, так что переменные типаnoalias<T, n>
иnoalias<T, m>
могут быть предположены никогда не псевдониму для n!= m.
Попытка
Вот мое глубоко ошибочное решение:
template <typename T, int n>
class noalias
{
struct T2 : T {};
T *t;
public:
noalias(T *t_) : t(t_) {}
T2 *operator->() const {return static_cast<T2*>(t);} // <-- UB
};
При доступе с помощью ->
он заносит внутренне сохраненный T*
в noalias<T, n>::T2*
и возвращает это вместо этого. Поскольку для каждого n
это другой тип, строгое правило сглаживания гарантирует, что он никогда не будет псевдонимом. Кроме того, поскольку t2
происходит от T
, возвращаемый указатель ведет себя как a T*
. Отлично!
Еще лучше, компиляция кода и выход сборки подтверждают, что он имеет желаемый эффект.
Проблема заключается в static_cast
. Если T
действительно указывали на объект типа t2
, тогда это было бы хорошо. Но T
указывает на a T
, так что это UB. На практике, поскольку t2
является подклассом, который ничего не добавляет к T
, он, вероятно, будет иметь тот же макет данных, и поэтому доступ членов к T2*
будет искать элементы с одинаковыми смещениями, как они встречаются в T
и все будет хорошо.
Но для строгого сглаживания необходим n
-зависимый класс и этот класс вытекает из T
, так что указатель можно рассматривать как a T*
. Поэтому UB кажется неизбежным.
Вопросы
-
Можно ли это сделать в С++ 14 без вызова UB - возможно, используя совершенно другую идею?
-
Если нет, то я слышал о "точечном операторе" в С++ 1z; было бы возможно с этим?
-
Если выше, будет ли что-то похожее на
noalias
появляться в стандартной библиотеке?