|
| 1 | +// Copyright David Abrahams 2002. Permission to copy, use, |
| 2 | +// modify, sell and distribute this software is granted provided this |
| 3 | +// copyright notice appears in all copies. This software is provided |
| 4 | +// "as is" without express or implied warranty, and with no claim as |
| 5 | +// to its suitability for any purpose. |
| 6 | +#ifndef AS_TO_PYTHON_FUNCTION_DWA2002121_HPP |
| 7 | +# define AS_TO_PYTHON_FUNCTION_DWA2002121_HPP |
| 8 | +# include <boost/python/converter/to_python_function_type.hpp> |
| 9 | + |
| 10 | +namespace boost { namespace python { namespace converter { |
| 11 | + |
| 12 | +// Given a typesafe to_python conversion function, produces a |
| 13 | +// to_python_function_t which can be registered in the usual way. |
| 14 | +template <class T, class ToPython> |
| 15 | +struct as_to_python_function |
| 16 | +{ |
| 17 | + // Assertion functions used to prevent wrapping of converters |
| 18 | + // which take non-const reference parameters. The T* argument in |
| 19 | + // the first overload ensures it isn't used in case T is a |
| 20 | + // reference. |
| 21 | + template <class U> |
| 22 | + static int convert_function_must_take_value_or_const_reference(U(*)(T), int, T* = 0); |
| 23 | + template <class U> |
| 24 | + static int convert_function_must_take_value_or_const_reference(U(*)(T const&), long ...); |
| 25 | + |
| 26 | + static PyObject* convert(void const* x) |
| 27 | + { |
| 28 | + BOOST_STATIC_ASSERT( |
| 29 | + sizeof( |
| 30 | + convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L)) |
| 31 | + == sizeof(int)); |
| 32 | + |
| 33 | + // Yes, the const_cast below opens a hole in const-correctness, |
| 34 | + // but it's needed to convert auto_ptr<U> to python. |
| 35 | + // |
| 36 | + // How big a hole is it? It allows ToPython::convert() to be |
| 37 | + // a function which modifies its argument. The upshot is that |
| 38 | + // client converters applied to const objects may invoke |
| 39 | + // undefined behavior. The damage, however, is limited by the |
| 40 | + // use of the assertion function. Thus, the only way this can |
| 41 | + // modify its argument is if T is an auto_ptr-like type. There |
| 42 | + // is still a const-correctness hole w.r.t. auto_ptr<U> const, |
| 43 | + // but c'est la vie. |
| 44 | + return ToPython::convert(*const_cast<T*>(static_cast<T const*>(x))); |
| 45 | + } |
| 46 | +}; |
| 47 | + |
| 48 | +}}} // namespace boost::python::converter |
| 49 | + |
| 50 | +#endif // AS_TO_PYTHON_FUNCTION_DWA2002121_HPP |
0 commit comments