Учитывая класс шаблона матрицы mat<M,N,T>
, следующая функция-член позволяет мне эффективно транспонировать вектор-строку или вектор-столбец, поскольку они имеют одинаковый/соответствующий объем памяти:
template<int M, int N=M, typename T = double>
struct mat {
// ...
template<int Md = M, int Nd = N, typename = std::enable_if_t<Md == 1 || Nd == 1>>
const mat<N, M, T>& transposedView() const {
static_assert(M == 1 || N == 1, "transposedView() supports only vectors, not general matrices.");
return *reinterpret_cast<const mat<N, M, T>*>(this);
}
}
Я использовал эту функцию в течение многих лет и по привычке начал вызывать ее для временных выражений (/*vector-valued expression*/).transposedView()
, забывая, что тогда она вернет ссылку на временное и приведет к неопределенному поведению, из-за которого GCC меня просто укусил.
Есть ли простой способ добавить что-то, что будет генерировать какое-то предупреждение, когда я вызываю его временно?
Или на самом деле должно быть безопасно вызывать его временно, пока я не сохраняю ссылку?
mat<N, M, T>
, где такого объекта нет (если толькоM
иN
оба не равны 1). Затем разыменование этого указателя является нарушением правил псевдонимов типов. В основном компилятор предполагает, что возвращенный указатель указывает на объект, отличный отthis
, потому что они указывают на разные типы. Иногда это не вызывает проблем, но компилятор может нарушить поведение вашего кода при попытке оптимизации. - person François Andrieux   schedule 29.07.2021reinterpret_cast
в этом случае автоматически является Undefined Behavior (опять же, еслиmat<N,M,T>
не имеет того же типа, что иmat<M,N,T>
). Как правило, еслиreinterpret_cast
кажется, что он решает проблему, скорее всего, это не так. В большинстве случаев единственное, что вы можете с ним сделать, — это вернуть объекту его истинный первоначальный тип. - person François Andrieux   schedule 29.07.2021mat<N,1,T>
иmat<1,N,T>
содержат толькоstd::array<T,N>
и никаких других элементов данных. Это все еще УБ? - person Museful   schedule 29.07.2021std::complex
имеет аналогичную проблему, поскольку массивы комплексных чисел обычно передаются в/из библиотек C. Таким образом, стандартная библиотека обходит UB, объявляя его неприменимым к std::complex в некоторых случаях. - person doug   schedule 29.07.2021reinterpret_cast
вообще называется этим именем.) - person Museful   schedule 29.07.2021memcpy
(если типы действительно POD). В большинстве случаев компилятор оптимизируетmemcpy
, но я не думаю, что в вашем случае такая оптимизация будет вероятной. - person François Andrieux   schedule 29.07.2021