Modernize ProductParameterization.
This CL modernizes ProductParameterization in the following ways:
- It uses std::unique_ptr for memory handling instead of using raw
pointers and handmade memory management.
- Replaces the constructors with a variadic template.
Change-Id: I5c9fe42ac935b6c26e867dbd3369a4c766623047
diff --git a/include/ceres/local_parameterization.h b/include/ceres/local_parameterization.h
index 5eed035..338ab54 100644
--- a/include/ceres/local_parameterization.h
+++ b/include/ceres/local_parameterization.h
@@ -32,9 +32,11 @@
#ifndef CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
#define CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
+#include <array>
+#include <memory>
#include <vector>
-#include "ceres/internal/port.h"
#include "ceres/internal/disable_warnings.h"
+#include "ceres/internal/port.h"
namespace ceres {
@@ -269,9 +271,6 @@
// manifolds. For example the parameters of a camera consist of a
// rotation and a translation, i.e., SO(3) x R^3.
//
-// Currently this class supports taking the cartesian product of up to
-// four local parameterizations.
-//
// Example usage:
//
// ProductParameterization product_param(new QuaterionionParameterization(),
@@ -282,22 +281,37 @@
class CERES_EXPORT ProductParameterization : public LocalParameterization {
public:
//
- // NOTE: All the constructors take ownership of the input local
+ // NOTE: The constructor takes ownership of the input local
// parameterizations.
//
- ProductParameterization(LocalParameterization* local_param1,
- LocalParameterization* local_param2);
+ template <typename... LocalParams>
+ ProductParameterization(LocalParams*... local_params)
+ : local_params_(sizeof...(LocalParams)),
+ local_size_{0},
+ global_size_{0},
+ buffer_size_{0} {
+ constexpr int kNumLocalParams = sizeof...(LocalParams);
+ static_assert(kNumLocalParams >= 2,
+ "At least two local parameterizations must be specified.");
- ProductParameterization(LocalParameterization* local_param1,
- LocalParameterization* local_param2,
- LocalParameterization* local_param3);
+ using LocalParameterizationPtr = std::unique_ptr<LocalParameterization>;
- ProductParameterization(LocalParameterization* local_param1,
- LocalParameterization* local_param2,
- LocalParameterization* local_param3,
- LocalParameterization* local_param4);
+ // Wrap all raw pointers into std::unique_ptr for exception safety.
+ std::array<LocalParameterizationPtr, kNumLocalParams> local_params_array{
+ LocalParameterizationPtr(local_params)...};
- virtual ~ProductParameterization();
+ // Initialize internal state.
+ for (int i = 0; i < kNumLocalParams; ++i) {
+ LocalParameterizationPtr& param = local_params_[i];
+ param = std::move(local_params_array[i]);
+
+ buffer_size_ =
+ std::max(buffer_size_, param->LocalSize() * param->GlobalSize());
+ global_size_ += param->GlobalSize();
+ local_size_ += param->LocalSize();
+ }
+ }
+
virtual bool Plus(const double* x,
const double* delta,
double* x_plus_delta) const;
@@ -307,9 +321,7 @@
virtual int LocalSize() const { return local_size_; }
private:
- void Init();
-
- std::vector<LocalParameterization*> local_params_;
+ std::vector<std::unique_ptr<LocalParameterization>> local_params_;
int local_size_;
int global_size_;
int buffer_size_;
diff --git a/internal/ceres/local_parameterization.cc b/internal/ceres/local_parameterization.cc
index 02ed4c9..4d63594 100644
--- a/internal/ceres/local_parameterization.cc
+++ b/internal/ceres/local_parameterization.cc
@@ -287,62 +287,12 @@
return true;
}
-ProductParameterization::ProductParameterization(
- LocalParameterization* local_param1,
- LocalParameterization* local_param2) {
- local_params_.push_back(local_param1);
- local_params_.push_back(local_param2);
- Init();
-}
-
-ProductParameterization::ProductParameterization(
- LocalParameterization* local_param1,
- LocalParameterization* local_param2,
- LocalParameterization* local_param3) {
- local_params_.push_back(local_param1);
- local_params_.push_back(local_param2);
- local_params_.push_back(local_param3);
- Init();
-}
-
-ProductParameterization::ProductParameterization(
- LocalParameterization* local_param1,
- LocalParameterization* local_param2,
- LocalParameterization* local_param3,
- LocalParameterization* local_param4) {
- local_params_.push_back(local_param1);
- local_params_.push_back(local_param2);
- local_params_.push_back(local_param3);
- local_params_.push_back(local_param4);
- Init();
-}
-
-ProductParameterization::~ProductParameterization() {
- for (int i = 0; i < local_params_.size(); ++i) {
- delete local_params_[i];
- }
-}
-
-void ProductParameterization::Init() {
- global_size_ = 0;
- local_size_ = 0;
- buffer_size_ = 0;
- for (int i = 0; i < local_params_.size(); ++i) {
- const LocalParameterization* param = local_params_[i];
- buffer_size_ = std::max(buffer_size_,
- param->LocalSize() * param->GlobalSize());
- global_size_ += param->GlobalSize();
- local_size_ += param->LocalSize();
- }
-}
-
bool ProductParameterization::Plus(const double* x,
const double* delta,
double* x_plus_delta) const {
int x_cursor = 0;
int delta_cursor = 0;
- for (int i = 0; i < local_params_.size(); ++i) {
- const LocalParameterization* param = local_params_[i];
+ for (const auto& param : local_params_) {
if (!param->Plus(x + x_cursor,
delta + delta_cursor,
x_plus_delta + x_cursor)) {
@@ -363,8 +313,7 @@
int x_cursor = 0;
int delta_cursor = 0;
- for (int i = 0; i < local_params_.size(); ++i) {
- const LocalParameterization* param = local_params_[i];
+ for (const auto& param : local_params_) {
const int local_size = param->LocalSize();
const int global_size = param->GlobalSize();