// Copyright (c) 2017 Commissariat à l'énergie atomique et aux énergies alternatives (CEA) // Copyright (c) 2017 Centre national de la recherche scientifique (CNRS) // Copyright (c) 2020 Simons Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0.txt // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Authors: Olivier Parcollet, Nils Wentzell #pragma once #include #include #include "../traits.hpp" #include "../pyref.hpp" namespace cpp2py { // std::variant converter // converts in the first possible type template struct py_converter> { private: // using variant_t = std::variant; template using types_t = std::tuple_element_t>; //constexpr static int n_types = sizeof...(T); // c2py_visitor //struct c2py_visitor { //template PyObject *operator()(T const &x) { return py_converter::c2py(x); } //}; // is_convertible_impl /* template static std::enable_if_t<(N < n_types), bool> is_convertible_impl(PyObject *ob) {*/ //return py_converter>::is_convertible(ob, false) || is_convertible_impl(ob); //} //template static std::enable_if_t is_convertible_impl(PyObject *ob) { return false; } // py2c_impl //template static std::enable_if_t<(N < n_types), variant_t> py2c_impl(PyObject *ob) { //if (py_converter>::is_convertible(ob, false)) //return py_converter>::py2c(ob); //else //return py2c_impl(ob); //} //template static std::enable_if_t py2c_impl(PyObject *ob) { //CPP2PY_RUNTIME_ERROR << "Internal error: py2c called for a Python object incompatible with std::variant"; //} template static std::variant py2c_impl(PyObject *ob) { using conv = py_converter>>; if (conv::is_convertible(ob, false)) return conv::py2c(ob); if constexpr (N < sizeof...(T) - 1) return py2c_impl(ob); else CPP2PY_RUNTIME_ERROR << "Internal error: py2c called for a Python object incompatible with std::variant"; } struct _visitor { template PyObject *operator()(U &&x) { return convert_to_python(std::forward(x)); } }; public: template static PyObject *c2py(V &&v) { static_assert(is_instantiation_of_v>); return visit(_visitor{}, std::forward(v)); } static bool is_convertible(PyObject *ob, bool raise_exception) { if ((... or py_converter>::is_convertible(ob, false))) return true; if (raise_exception) { PyErr_SetString(PyExc_TypeError, ("Cannot convert "s + to_string(ob) + " to std::variant"s).c_str()); } return false; } static std::variant py2c(PyObject *ob) { return py2c_impl<0>(ob); } }; } // namespace cpp2py