|
Boost : |
From: Stefan Slapeta (stefan_at_[hidden])
Date: 2005-02-24 09:31:41
Vladimir Prus wrote:
>
> Can you give the specific use cases. I think that fully generic solution can
> be overly complex, and we can get away with some helper functions. Say,
> 'mutially_excluse_options' can check than only one option of a group is
> specified.
>
what about this syntax?
po::options_validator v =
( po::exists("option_a") & po::exists("option_c")
|
( po::exists("option_c") & po::exists("option_d")
;
bool valid = v.validate(desc);
I attach a working basic solution (many things copied from spirit ;) ),
feel free to do anything you want with it.
I used operator ^ for mutually exclusive options, but I'm afraid it's
not perfect as it's not the same as xor!
Cheers,
Stefan
#ifndef VALIDATOR_H_INCLUDED
#define VALIDATOR_H_INCLUDED
// Copyright Stefan Slapeta 2005.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/shared_ptr.hpp>
#include <boost/compressed_pair.hpp>
#include <boost/program_options/options_description.hpp>
namespace boost { namespace program_options {
template <typename DerivedT>
class validator_base
{
public:
bool validate(options_description const& desc) const
{
return derived().do_validate(desc);
}
DerivedT const& derived() const
{
return *static_cast<DerivedT const*>(this);
}
DerivedT& derived()
{
return *static_cast<DerivedT*>(this);
}
};
template <typename L, typename R, typename BaseT>
class binary_validator : public BaseT
{
public:
typedef typename boost::call_traits<L>::param_type left_param_t;
typedef typename boost::call_traits<L>::const_reference left_return_t;
typedef typename boost::call_traits<R>::param_type right_param_t;
typedef typename boost::call_traits<R>::const_reference right_return_t;
typedef typename boost::remove_reference<L>::type left_embed_t;
typedef typename boost::remove_reference<R>::type right_embed_t;
binary_validator(left_param_t left, right_param_t right)
: m_subj(left, right)
{
}
left_return_t left() const {
return m_subj.first();
}
right_return_t right() const {
return m_subj.second();
}
private:
boost::compressed_pair<left_embed_t, right_embed_t> m_subj;
};
template <typename L, typename R>
class exists_composite :
public binary_validator<L, R, validator_base<exists_composite<L, R> > >
{
public:
typedef exists_composite<L, R> self_t;
typedef binary_validator<L, R, validator_base<self_t> > base_t;
exists_composite(L const& left, R const& right)
: base_t(left, right)
{
}
bool do_validate(options_description const& desc) const
{
return left().validate(desc) && right().validate(desc);
}
};
template <typename L, typename R>
class exists_alternative :
public binary_validator<L, R, validator_base<exists_alternative<L, R> > >
{
public:
typedef exists_alternative<L, R> self_t;
typedef binary_validator<L, R, validator_base<self_t> > base_t;
exists_alternative(L const& left, R const& right)
: base_t(left, right)
{
}
bool do_validate(options_description const& desc) const
{
return left().validate(desc) || right().validate(desc);
}
};
template <typename L, typename R>
class mutually_exclusive :
public binary_validator<L, R, validator_base<mutually_exclusive<L, R> > >
{
public:
typedef mutually_exclusive<L, R> self_t;
typedef binary_validator<L, R, validator_base<self_t> > base_t;
mutually_exclusive(L const& left, R const& right)
: base_t(left, right)
{
}
bool do_validate(options_description const& desc) const
{
return left().validate(desc) || right().validate(desc);
}
};
class exists :
public validator_base<exists>
{
public:
exists(std::string const& option)
: m_option(option)
{
}
bool do_validate(options_description const& desc) const
{
return desc.count(m_option) != 0;
}
private:
std::string m_option;
};
template <typename LeftValidatorT, typename RightValidatorT>
exists_alternative<LeftValidatorT, RightValidatorT>
operator | (validator_base<LeftValidatorT> const& l, validator_base<RightValidatorT> const& r)
{
return exists_alternative<LeftValidatorT, RightValidatorT>(l.derived(), r.derived());
}
template <typename LeftValidatorT, typename RightValidatorT>
exists_composite<LeftValidatorT, RightValidatorT>
operator & (validator_base<LeftValidatorT> const& l, validator_base<RightValidatorT> const& r)
{
return exists_composite<LeftValidatorT, RightValidatorT>(l.derived(), r.derived());
}
template <typename LeftValidatorT, typename RightValidatorT>
mutually_exclusive<LeftValidatorT, RightValidatorT>
operator ^ (validator_base<LeftValidatorT> const& l, validator_base<RightValidatorT> const& r)
{
return mutually_exclusive<LeftValidatorT, RightValidatorT>(l.derived(), r.derived());
}
class validator_impl_base
{
public:
bool validate(options_description const& desc) const
{
return validate_virtual(desc);
}
private:
virtual bool validate_virtual(options_description const& desc) const = 0;
};
template <typename ValidatorT>
class validator_impl : public validator_impl_base
{
public:
validator_impl(ValidatorT const& v)
: m_validator(v)
{
}
private:
bool validate_virtual(options_description const& desc) const
{
return m_validator.validate(desc);
}
ValidatorT m_validator;
};
class options_validator
{
public:
template <typename ValidatorT>
options_validator(validator_base<ValidatorT> const& v)
: m_validator(new validator_impl<ValidatorT>(v.derived()))
{
}
bool validate(options_description const& desc) const
{
return m_validator->validate(desc);
}
private:
boost::shared_ptr<validator_impl_base> m_validator;
};
}}
#endif
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk