1 // Copyright (c) 2017 Commissariat à l'énergie atomique et aux énergies alternatives (CEA) 2 // Copyright (c) 2017 Centre national de la recherche scientifique (CNRS) 3 // Copyright (c) 2020 Simons Foundation 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0.txt 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // Authors: Olivier Parcollet, Nils Wentzell 18 19 #pragma once 20 #include "../traits.hpp" 21 #include "../pyref.hpp" 22 23 namespace cpp2py { 24 25 template <typename T1, typename T2> struct py_converter<std::pair<T1, T2>> { 26 c2pycpp2py::py_converter27 template <typename P> static PyObject *c2py(P &&p) { 28 static_assert(is_instantiation_of_v<std::pair, std::decay_t<P>>, "Logic error"); 29 pyref x1 = convert_to_python(std::get<0>(std::forward<P>(p))); 30 pyref x2 = convert_to_python(std::get<1>(std::forward<P>(p))); 31 32 if (x1.is_null() or x2.is_null()) return NULL; 33 return PyTuple_Pack(2, (PyObject *)x1, (PyObject *)x2); 34 } 35 is_convertiblecpp2py::py_converter36 static bool is_convertible(PyObject *ob, bool raise_exception) { 37 if (!PySequence_Check(ob)) goto _false; 38 { 39 pyref seq = PySequence_Fast(ob, "expected a sequence"); 40 if (!py_converter<T1>::is_convertible(PySequence_Fast_GET_ITEM((PyObject *)seq, 0), raise_exception)) goto _false; // borrowed ref 41 if (!py_converter<T2>::is_convertible(PySequence_Fast_GET_ITEM((PyObject *)seq, 1), raise_exception)) goto _false; // borrowed ref 42 return true; 43 } 44 _false: 45 if (raise_exception) { PyErr_SetString(PyExc_TypeError, ("Cannot convert "s + to_string(ob) + " to std::pair"s).c_str()); } 46 return false; 47 } 48 py2ccpp2py::py_converter49 static std::pair<T1, T2> py2c(PyObject *ob) { 50 pyref seq = PySequence_Fast(ob, "expected a sequence"); 51 return std::make_pair(py_converter<T1>::py2c(PySequence_Fast_GET_ITEM((PyObject *)seq, 0)), 52 py_converter<T2>::py2c(PySequence_Fast_GET_ITEM((PyObject *)seq, 1))); 53 } 54 }; 55 } // namespace cpp2py 56