xtensor-stack / xtensor-python

Python bindings for xtensor
BSD 3-Clause "New" or "Revised" License
347 stars 58 forks source link

Ambigous overload resolution #203

Closed serge-sans-paille closed 4 years ago

serge-sans-paille commented 5 years ago

The following snippet fails to compile

#include "xtensor-python/pyarray.hpp"
#include "xtensor-python/pytensor.hpp"

auto xtensor_test(xt::pytensor<double, 3>& arr, xt::xtensor<double, 3> const& x) {
  arr /= x;
  return arr;
}

while this one is OK

#include "xtensor-python/pyarray.hpp"
#include "xtensor-python/pytensor.hpp"

auto xtensor_test(xt::pytensor<double, 3>& arr, xt::xtensor<double, 3> const& x) {
  arr = arr / x;
  return arr;
}

tested with clang 6 and gcc 8, xtensor 0.20.8 and xtensor-python 0.23.1

Error log:

In file included from /home/sguelton/.venvs/numpy-benchmarks/include/xtensor-python/pyarray.hpp:20,
                 from a.cpp:2:
/home/sguelton/.venvs/numpy-benchmarks/include/xtensor-python/pycontainer.hpp: In instantiation of ‘class xt::pycontainer<xt::pytensor<double, 3> >’:
/home/sguelton/.venvs/numpy-benchmarks/include/xtensor-python/pytensor.hpp:143:11:   required from ‘class xt::pytensor<double, 3>’
a.cpp:6:11:   required from here
/home/sguelton/.venvs/numpy-benchmarks/include/xtensor-python/pycontainer.hpp:53:11: warning: ‘xt::pycontainer<xt::pytensor<double, 3> >’ declared with greater visibility than its base ‘pybind11::object’ [-Wattributes]
     class pycontainer : public pybind11::object,
           ^~~~~~~~~~~
a.cpp: In function ‘auto xtensor_test(xt::pytensor<double, 3>&, xt::xtensor<double, 3>&)’:
a.cpp:6:11: error: request for member ‘operator/=’ is ambiguous
   arr /=  x;
           ^
In file included from /home/sguelton/.venvs/numpy-benchmarks/include/xtensor-python/pyarray.hpp:18,
                 from a.cpp:2:
/home/sguelton/.venvs/numpy-benchmarks/include/xtensor/xsemantic.hpp:74:23: note: candidates are: ‘template<class E> xt::xsemantic_base<D>::derived_type& xt::xsemantic_base<D>::operator/=(const xt::xexpression<E1>&) [with E = E; D = xt::pytensor<double, 3>]’
         derived_type& operator/=(const xexpression<E>&);
                       ^~~~~~~~
/home/sguelton/.venvs/numpy-benchmarks/include/xtensor/xsemantic.hpp:50:47: note:                 ‘template<class E> xt::disable_xexpression<E, typename xt::xexpression<E>::derived_type&> xt::xsemantic_base<D>::operator/=(const E&) [with E = E; D = xt::pytensor<double, 3>]’
         disable_xexpression<E, derived_type&> operator/=(const E&);
                                               ^~~~~~~~
In file included from /home/sguelton/.venvs/numpy-benchmarks/include/pybind11/cast.h:13,
                 from /home/sguelton/.venvs/numpy-benchmarks/include/pybind11/attr.h:13,
                 from /home/sguelton/.venvs/numpy-benchmarks/include/pybind11/pybind11.h:44,
                 from /home/sguelton/.venvs/numpy-benchmarks/include/pybind11/complex.h:12,
                 from /home/sguelton/.venvs/numpy-benchmarks/include/xtensor-python/pycontainer.hpp:16,
                 from /home/sguelton/.venvs/numpy-benchmarks/include/xtensor-python/pyarray.hpp:20,
                 from a.cpp:2:
/home/sguelton/.venvs/numpy-benchmarks/include/pybind11/pytypes.h:134:12: note:                 ‘pybind11::object pybind11::detail::object_api<Derived>::operator/=(const pybind11::detail::object_api<Derived>&) const [with Derived = pybind11::handle]’
     object operator/=(object_api const &other) const;
            ^~~~~~~~
drmoose commented 4 years ago

This same issue came up for me when upgrading pybind11. Here's a test program I made to try to find the problem, in which changing pybind versions, holding everything else constant, is sufficient to trigger compiler errors like this one. The working and broken versions of pybind11 I used are 2.2.4 and 2.4.0 respectively.

SylvainCorlay commented 4 years ago

object operator/=(object_api const &other) const

Yes, that is a very generic overload in pybind11.

@wjakob do you know if it would be possible to make this a bit more restricive so that it does not conflict with other py:object implementing their operators?