У меня есть значение функции (x), которое перегружено для многих типов, таких как:
double value(double x) { return x; }
double value(MyType x) { return x.value(); }
SomeContainer<double> value(SomeContainer<double> x) { return x; }
SomeContainer<double> value(SomeContainer<MyType> x) { ... }
где MyType на самом деле представляет собой число с вектором градиента относительно набора параметров.
для использования в общих (шаблонных) программах.
Я хочу определить:
Matrix<double> value(Matrix<double>)
Matrix<double> value(Matrix<MyType>)
Я использую собственные матрицы, и это моя текущая реализация первой функции:
template < typename Derived,
typename std::enable_if< std::is_floating_point< typename Derived::Scalar >::value, int >::type = 0 >
Derived value( const Eigen::MatrixBase< Derived >& matrix )
{
return matrix;
}
Проблема в том, что это кажется неэффективным, если только в возможных случаях, когда компилятор может выяснить, что результат / аргумент не изменяется, и ускользнуть от копии. Я также не могу вернуть ссылку на аргумент, поскольку он является локальным / временным.
По сути, мне бы хотелось, чтобы значение (x) компилировалось как само выражение аргумента, если аргумент представляет собой матрицу типа double / float. Я не понимаю, как я могу добиться этого с помощью шаблона функции, и макрос не позволит специализации.
Что можно сделать, чтобы избежать копирования?
РЕДАКТИРОВАТЬ 22 марта 2019 г .:
Если заменить тип возврата на
const Derived &
Я получаю следующее предупреждение GCC:
warning: returning reference to temporary [-Wreturn-local-addr]
в следующем коде:
Matrix33 m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << m << std::endl;
std::cout << value(m) << std::endl;
и значение (m) распечатывается как мусор.
Также я все больше думаю о том, что было бы плохой идеей «вернуть сам объект», потому что он будет использоваться в универсальном коде:
auto m = value(Mx)
где Mx - матрица X (параметр шаблона), а m - двойная матрица.
Наличие другой семантики (кража объекта в случае двойного X и создание отдельного объекта в других случаях) может привести ко многим ошибкам программирования.
Другая возможность - возвращать прокси-объекты.
Лучше всего, однако, чтобы компилятор видел, когда копия не нужна, потому что ничего не меняется. Однако, похоже, это не так: мой тест для сравнения
Matrix<double,3,3> M = ...
norm(M)
и
Matrix<double,3,3> M = ...
norm(value(M))
показывает, что вторая версия немного медленнее в (оптимизированной) сборке.