Boost logo

Boost :

Subject: Re: [boost] [contract] syntax redesign
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-12-11 06:37:35


On Wed, Nov 9, 2011 at 6:16 AM, Lorenzo Caminiti <lorcaminiti_at_[hidden]> wrote:
>>> The goal here is to use Boost.Contract to /completely/ specify the
>>> interface for the positive abstract data type.

For whomever is curious, the Boost.Contract named and deduced
parameter examples now compile:
https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contract__/examples.html#contract__.examples.__named_parameters___depth_first_search__required_and_optional_named_parameters

Here's an example that uses a bit of everything: Contracts, concepts,
named/deduced function and template parameters:

#include <boost/python.hpp>
#include <contract.hpp>
#include <contract/parameter.hpp> // For named parameters.
#include <contract/concept.hpp> // For concepts.
#include <boost/concept_check.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/regex.hpp>

namespace py {

// Helpers.

bool is_identifier ( char const* name )
{
    static const boost::regex re("(\\l|\\u|_)(\\l|\\u|\\d|_)*");
    return boost::regex_match(name, re);
}

// Class template with named parameters.

CONTRACT_TEMPLATE_PARAMETER(ClassType)
CONTRACT_TEMPLATE_PARAMETER(Bases)
CONTRACT_TEMPLATE_PARAMETER(HeldType)
CONTRACT_TEMPLATE_PARAMETER(Copyable)
CONTRACT_PARAMETER(name)

CONTRACT_CLASS(
template(
    // Required named template parameter.
    in typename requires(boost::is_class<boost::mpl::_>) ClassType,
    // Deduced and optional named template parameters with type requirements.
    deduce in typename requires(boost::python::detail::specifies_bases<
            boost::mpl::_>) Bases,
            default boost::python::bases<>,
    deduce in typename requires(BOOST_IDENTITY_TYPE((boost::mpl::not_<
                boost::mpl::or_<
                      boost::python::detail::specifies_bases<boost::mpl::_>
                    , boost::is_same<boost::noncopyable, boost::mpl::_>
>
>))) HeldType,
            default boost::python::detail::not_specified,
    deduce in typename requires(BOOST_IDENTITY_TYPE((
                boost::is_same<boost::noncopyable, boost::mpl::_>
            ))) Copyable,
            default boost::python::detail::not_specified
    // Note: Non-type template parameters are not supported by named parameters.
) requires( boost::DefaultConstructible<ClassType> ) // Concepts.
class (class_) extends( BOOST_IDENTITY_TYPE((
        boost::python::class_<ClassType, Bases, HeldType, Copyable>)) )
) {
    CONTRACT_CLASS_INVARIANT_TPL( void ) // Contracts.

    typedef boost::python::class_<ClassType, Bases, HeldType, Copyable>
            boost_python_class;

public:

    CONTRACT_CONSTRUCTOR_TPL(
    public (class_) ( in (char const*) name )
        precondition( is_identifier(name) )
        initialize( boost_python_class(CONTRACT_CONSTRUCTOR_ARG(name)) )
    ) {}
};

} // namespace py

struct bx { virtual ~bx ( void ) {} };
struct x : bx {};

struct by { virtual ~by ( void ) {} };
struct y : by { };

// Python module, in a Python shell from this directory run:
// >>> import pyclass # This will check contracts (preconditions, etc).
// >>> help("pyclass"), xx = pyclass.x(), yy = pyclass.x()
BOOST_PYTHON_MODULE(pyclass)
{
    // Named parameters.
    py::class_<py::_ClassType<bx>, py::_Copyable<boost::noncopyable> >("bx");
    py::class_<x, py::_HeldType<boost::shared_ptr<x> >,
            py::_Bases<boost::python::bases<bx> > >("x");
    // Deduced parameters.
    py::class_<by, boost::noncopyable>("by");
    py::class_<y, boost::shared_ptr<y>, boost::python::bases<by> >(
            py::_name = "y");
}

Comments welcome.
--Lorenzo


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk