Skip to content

Commit

Permalink
Add fix for std::optional<Eigen::Ref<const T>>
Browse files Browse the repository at this point in the history
  • Loading branch information
ManifoldFR committed Aug 27, 2024
1 parent f0aa786 commit 514212c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
2 changes: 1 addition & 1 deletion bindings/python/src/expose-results.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <nanobind/eigen/dense.h>
#include <nanobind/eigen/sparse.h>
#include <nanobind/operators.h>
#include <nanobind/stl/optional.h>
#include "optional-eigen-fix.hpp"

#include <proxsuite/helpers/optional.hpp>
#include <proxsuite/serialization/archive.hpp>
Expand Down
2 changes: 1 addition & 1 deletion bindings/python/src/expose-solve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <nanobind/nanobind.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/eigen/sparse.h>
#include <nanobind/stl/optional.h>
#include "optional-eigen-fix.hpp"

namespace proxsuite {
namespace proxqp {
Expand Down
45 changes: 45 additions & 0 deletions bindings/python/src/optional-eigen-fix.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Copyright (c) 2024 INRIA
//
#pragma once

#include <nanobind/stl/optional.h>
#include <Eigen/Core>

NAMESPACE_BEGIN(NB_NAMESPACE)
NAMESPACE_BEGIN(detail)

/// Fix std::optional for Eigen::Ref<const T>
/// Credit to github.com/WKarel for this suggestion!
/// https://github.com/wjakob/nanobind/issues/682#issuecomment-2310746145
template<typename T>
struct type_caster<std::optional<Eigen::Ref<const T>>>
: optional_caster<std::optional<Eigen::Ref<const T>>>
{
using Ref = Eigen::Ref<const T>;
using Optional = std::optional<Ref>;
using Caster = typename type_caster::optional_caster::Caster;
using Map = typename Caster::Map;
using DMap = typename Caster::DMap;
NB_TYPE_CASTER(Optional, optional_name(Caster::Name))

bool from_python(handle src, uint8_t flags, cleanup_list* cleanup) noexcept
{
if (src.is_none())
return true;
Caster caster;
if (!caster.from_python(src, flags_for_local_caster<T>(flags), cleanup) ||
!caster.template can_cast<T>())
return false;
/// This allows us to bypass the type_caster for Eigen::Ref
/// which is broken due to lack of NRVO + move ctor in latest Eigen release.
if (caster.dcaster.caster.value.is_valid())
value.emplace(caster.dcaster.operator DMap());
else
value.emplace(caster.caster.operator Map());
return true;
}
};

NAMESPACE_END(detail)
NAMESPACE_END(NB_NAMESPACE)

0 comments on commit 514212c

Please sign in to comment.