Modernize CostFunction and FirstOrderFunction constructors

- Add constructors taking std::unique_ptr and ceres::Ownership to
  AutoDiffCostFunction, NumericDiffCostFunction, and their dynamic
  and first-order counterparts.
- Standardize delegating constructor style to use parentheses.
- Standardize ownership check in destructors.
- Fix documentation typos and example code in headers.
- Add comprehensive tests for Ownership and unique_ptr constructors.

Change-Id: I573abd695cdd89905997b573620e8d99d1cacca2
This commit is contained in:
Sameer Agarwal
2026-03-18 14:09:38 -07:00
parent 3abe9326f1
commit 3d1b494dce
9 changed files with 183 additions and 87 deletions
+23 -13
View File
@@ -186,32 +186,41 @@ class NumericDiffCostFunction final
Ownership ownership = TAKE_OWNERSHIP,
int num_residuals = kNumResiduals,
const NumericDiffOptions& options = NumericDiffOptions())
: NumericDiffCostFunction{std::unique_ptr<CostFunctor>{functor},
: NumericDiffCostFunction(std::unique_ptr<CostFunctor>(functor),
ownership,
num_residuals,
options} {}
options) {
if constexpr (kNumResiduals != DYNAMIC) {
DCHECK_EQ(num_residuals, kNumResiduals);
}
}
explicit NumericDiffCostFunction(
std::unique_ptr<CostFunctor> functor,
int num_residuals = kNumResiduals,
const NumericDiffOptions& options = NumericDiffOptions())
: NumericDiffCostFunction{
std::move(functor), TAKE_OWNERSHIP, num_residuals, options} {}
: NumericDiffCostFunction(
std::move(functor), TAKE_OWNERSHIP, num_residuals, options) {
if constexpr (kNumResiduals != DYNAMIC) {
DCHECK_EQ(num_residuals, kNumResiduals);
}
}
// Constructs the CostFunctor on the heap and takes the ownership.
// Invocable only if the number of residuals is known at compile-time.
template <class... Args,
bool kIsDynamic = kNumResiduals == DYNAMIC,
std::enable_if_t<!kIsDynamic &&
std::is_constructible_v<CostFunctor, Args&&...>>* =
nullptr>
typename = std::enable_if_t<
(kNumResiduals != DYNAMIC) &&
std::is_constructible_v<CostFunctor, Args&&...>>>
explicit NumericDiffCostFunction(Args&&... args)
// NOTE We explicitly use direct initialization using parentheses instead
// of uniform initialization using braces to avoid narrowing conversion
// warnings.
: NumericDiffCostFunction{
: NumericDiffCostFunction(
std::make_unique<CostFunctor>(std::forward<Args>(args)...),
TAKE_OWNERSHIP} {}
TAKE_OWNERSHIP,
kNumResiduals,
NumericDiffOptions()) {}
NumericDiffCostFunction(NumericDiffCostFunction&& other) noexcept = default;
NumericDiffCostFunction& operator=(NumericDiffCostFunction&& other) noexcept =
@@ -220,7 +229,7 @@ class NumericDiffCostFunction final
NumericDiffCostFunction& operator=(const NumericDiffCostFunction&) = delete;
~NumericDiffCostFunction() override {
if (ownership_ != TAKE_OWNERSHIP) {
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
functor_.release();
}
}
@@ -229,7 +238,6 @@ class NumericDiffCostFunction final
double* residuals,
double** jacobians) const override {
using absl::FixedArray;
using internal::NumericDiff;
using ParameterDims =
typename SizedCostFunction<kNumResiduals, Ns...>::ParameterDims;
@@ -275,11 +283,13 @@ class NumericDiffCostFunction final
private:
explicit NumericDiffCostFunction(std::unique_ptr<CostFunctor> functor,
Ownership ownership,
[[maybe_unused]] int num_residuals,
int num_residuals,
const NumericDiffOptions& options)
: functor_(std::move(functor)), ownership_(ownership), options_(options) {
if constexpr (kNumResiduals == DYNAMIC) {
this->set_num_residuals(num_residuals);
} else {
DCHECK_EQ(num_residuals, kNumResiduals);
}
}