Boost logo

Boost :

Subject: [boost] [contract] with Boost.Parameter (was "Contract Programming Library")
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-04-15 15:59:07


On Wed, Feb 17, 2010 at 4:05 AM, Andrzej Krzemienski <akrzemi1_at_[hidden]> wrote:
>> > it is inevitable, etc., but.. read on. I know at least one library in
>> > Boost that also spoils function declarations in order to provide
>> > additional functionality: Concept Check library; they may be others
>> > too (MPL?).
>> > My suggestion is that if there are (or will be) libraries that require
>> > spoiling function declarations, they should all provide the same
>> > "spoiled" syntax. Otherwise I will be always asking "how do I declare
>> > a function in this library?". It would be very convenient if Boost
>> > provided one alternative function definition syntax that when used
>> > would enable all its libraries to work.
>>
>> I agree. However, in the past I did look into harmonizing my library
>> API with the ones of Boost.ConceptCheck and/or Boost.Parameter but it
>> did not seem feasible... I will double check it.
>
> This is not only about clarity. As a super-correct programmer I may want to
> apply both concept checking and pre-/post-conditions checking to my functions.
>
> Perhaps, if the 'compromise' syntax is possible, it requires changing
> concept-checking library.

I have verified that it is possible to use Boost.Parameter together
with the current implementation of Boost.Contract. However, I have not
yet verified compatibility with the entire set of Boost.Parameter
features (template parameters, free-functions, etc).

    #include <boost/parameter.hpp>
    #include <boost/graph/depth_first_search.hpp>
    #include <contract.hpp>
    #include <iostream>

    namespace graphs {

    BOOST_PARAMETER_NAME(graph)
    BOOST_PARAMETER_NAME(visitor)
    BOOST_PARAMETER_NAME(root_vertex)
    BOOST_PARAMETER_NAME(index_map)
    BOOST_PARAMETER_NAME(color_map)

    struct g {
        CONTRACT_CLASS( (g) )

        BOOST_PARAMETER_MEMBER_FUNCTION(
            (void),
            depth_first_search,
            tag,
            (required (graph, *) )
            (optional
                (visitor, *, boost::dfs_visitor<>())
                (root_vertex, *, *vertices(graph).first)
                (index_map, *, get(boost::vertex_index, graph))
                (in_out(color_map), *,
                        default_color_map(num_verticies(graph), index_map))
            )
        )
        CONTRACT_FUNCTION(
        (public) (template)(
                (typename)(graph_type)
                (typename)(visitor_type)
                (typename)(root_vertex_type)
                (typename)(index_map_type)
                (typename)(color_map_type)
                )
        (void) (depth_firt_search)(
                (graph_type&)(graph)
                (visitor_type&)(visitor)
                (root_vertex_type&)(root_vertex)
                (index_map_type&)(index_map)
                (copyable)(color_map_type&)(color_map)
                )
        (postcondition) ({
            CONTRACT_ASSERT( color_map == CONTRACT_OLDOF(color_map) + 10 );
        })
        (body) ({
            color_map += 10;
            std::cout << "graph=" << graph << std::endl;
            std::cout << "visitor=" << visitor << std::endl;
            std::cout << "root_vertex=" << root_vertex << std::endl;
            std::cout << "index_map=" << index_map << std::endl;
            std::cout << "color_map=" << color_map << std::endl;
        }) )
    };

    } // namespace

    int main() {
        using namespace graphs;
        g gg;
        int cm = 0;
        gg.depth_first_search(1, 2, 3, 4, cm);
        std::cout << std::endl;
        gg.depth_first_search("1", '2', _color_map = cm,
                _index_map = "4", _root_vertex = "3");
        return 0;
    }

This function declaration syntax is terrible as it mixes the syntactic
complexity of both Boost.Parameter and Boost.Contract... I will try to
provide the following syntax instead:

    CONTRACT_FUNCTION(
    (public) (void) (depth_first_search)( // No (tag)(namespace-id) so
use `tag`.
            // (auto) for no type requirements (preprocessor can't use `*`).
            (auto) (graph)
            // (default) for optional param.
            (auto) (visitor) (default)(boost::dfs_visitor<>())
            (auto) (root_vertex) (vertices(graph).first)
            (auto) (index_map) (default)(get(boost::vertex_index, graph))
            // (inout) for in-out type.
            (copyable)(inout)(auto) (color_map) (default)
                    (default_color_map(num_verticies(graph), index_map))
            // Plus, (deduced)( parameter-sequence ) for deduced params.
            )
        (postcondition) ( (color_map == CONTRACT_OLDOF(color_map) + 10) )
    ({
        color_map += 10;
        std::cout << "graph=" << graph << std::endl;
        ...
    })

(IMO, this syntax looks cleaner that the original Boost.Parameter one.)

-- 
Lorenzo

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