[modernize] Modernize AutoDiff and NumericDiff CostFunctions to C++17

Modernize the construction and initialization logic of AutoDiffCostFunction,
NumericDiffCostFunction, AutoDiffFirstOrderFunction,
NumericDiffFirstOrderFunction, DynamicAutoDiffCostFunction,
DynamicNumericDiffCostFunction, and CostFunctionToFunctor by utilizing
C++17 features:

- Simplify constructor delegation using if constexpr, removing the need for
  internal InitTag structures.
- Use std::is_constructible_v for cleaner SFINAE in variadic constructors.
- Add static_assert to catch improper usage of DYNAMIC residuals/parameters
  at compile-time.
- Add Ownership support to AutoDiffFirstOrderFunction,
  DynamicAutoDiffCostFunction, and DynamicNumericDiffCostFunction.
- Simplify CostFunctionToFunctor::operator() using variadic parameter packs.
- Use this->num_residuals() for consistent and clear access to base class
  state.
- Minor code quality improvements and removal of redundant template
  parameters.

Change-Id: Id760a26ba2ceca4fb2939ef7632f2f1d9cc430c9
This commit is contained in:
Sameer Agarwal
2026-03-17 14:36:58 -07:00
parent ae3f2e8683
commit bcbaff6656
6 changed files with 81 additions and 65 deletions
@@ -72,36 +72,39 @@ namespace ceres {
// also specify the sizes after creating the
// DynamicNumericDiffCostFunction. For example:
//
// DynamicAutoDiffCostFunction<MyCostFunctor, CENTRAL> cost_function;
// DynamicNumericDiffCostFunction<MyCostFunctor, CENTRAL> cost_function;
// cost_function.AddParameterBlock(5);
// cost_function.AddParameterBlock(10);
// cost_function.SetNumResiduals(21);
template <typename CostFunctor, NumericDiffMethodType kMethod = CENTRAL>
class DynamicNumericDiffCostFunction final : public DynamicCostFunction {
public:
explicit DynamicNumericDiffCostFunction(
const CostFunctor* functor,
Ownership ownership = TAKE_OWNERSHIP,
const NumericDiffOptions& options = NumericDiffOptions())
: DynamicNumericDiffCostFunction{
std::unique_ptr<const CostFunctor>{functor}, ownership, options} {}
// Takes ownership of functor by default.
explicit DynamicNumericDiffCostFunction(
std::unique_ptr<const CostFunctor> functor,
const NumericDiffOptions& options = NumericDiffOptions())
: DynamicNumericDiffCostFunction{
std::move(functor), TAKE_OWNERSHIP, options} {}
: DynamicNumericDiffCostFunction(
std::move(functor), TAKE_OWNERSHIP, options) {}
// Constructs the CostFunctor on the heap and takes the ownership.
template <class... Args,
std::enable_if_t<std::is_constructible_v<CostFunctor, Args&&...>>* =
nullptr>
typename = std::enable_if_t<std::is_constructible_v<CostFunctor,
Args&&...>>>
explicit DynamicNumericDiffCostFunction(Args&&... args)
// NOTE We explicitly use direct initialization using parentheses instead
// of uniform initialization using braces to avoid narrowing conversion
// warnings.
: DynamicNumericDiffCostFunction{
std::make_unique<CostFunctor>(std::forward<Args>(args)...)} {}
: DynamicNumericDiffCostFunction(
std::make_unique<const CostFunctor>(std::forward<Args>(args)...),
TAKE_OWNERSHIP,
NumericDiffOptions()) {}
explicit DynamicNumericDiffCostFunction(
const CostFunctor* functor,
Ownership ownership = TAKE_OWNERSHIP,
const NumericDiffOptions& options = NumericDiffOptions())
: DynamicNumericDiffCostFunction(
std::unique_ptr<const CostFunctor>(functor), ownership, options) {}
DynamicNumericDiffCostFunction(const DynamicNumericDiffCostFunction&) =
delete;
@@ -113,7 +116,7 @@ class DynamicNumericDiffCostFunction final : public DynamicCostFunction {
DynamicNumericDiffCostFunction&& other) noexcept = default;
~DynamicNumericDiffCostFunction() override {
if (ownership_ != TAKE_OWNERSHIP) {
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
functor_.release();
}
}
@@ -220,4 +223,4 @@ DynamicNumericDiffCostFunction(std::unique_ptr<CostFunctor> functor,
} // namespace ceres
#endif // CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
#endif // CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_