Hi all!

Suppose you'd want to implement a simple EDSL (Embedded Domain Specific Language) with Boost.proto with the following requirements:

    Custom class 'Vector' as terminal
    Classes derived from 'Vector' are working terminals too, e.g. Vector10

Reading the manual of Boost.proto it seems the closest related example to this would be the 'Vector: Adapting a Non-Proto Terminal Type' example.

Modifications I did to that example:

    Added 'Vector' class
    Protofied Vector instead of std::vector

Here the code (compiles):


// ------------------------------------------------------------

#include <vector>
#include <iostream>
#include <stdexcept>
#include <boost/mpl/bool.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/debug.hpp>
#include <boost/proto/context.hpp>
#include <boost/utility/enable_if.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
using proto::_;

class Vector;

template<typename Expr>
struct VectorExpr;

struct VectorSubscriptCtx
{
    VectorSubscriptCtx(std::size_t i)
      : i_(i)
    {}

    template<typename Expr, typename EnableIf = void>
    struct eval
      : proto::default_eval<Expr, VectorSubscriptCtx const>
    {};

    template<typename Expr>
    struct eval<
        Expr
      , typename boost::enable_if<
            proto::matches<Expr, proto::terminal< Vector > >
        >::type
    >
    {
typedef typename proto::result_of::value<Expr>::type::value_type result_type;

result_type operator ()(Expr &expr, VectorSubscriptCtx const &ctx) const
        {
            return proto::value(expr)[ctx.i_];
        }
    };

    std::size_t i_;
};




struct VectorGrammar : proto::or_<
    proto::terminal< proto::_ >,
    proto::plus< VectorGrammar, VectorGrammar>,
    proto::minus< VectorGrammar, VectorGrammar>
> {};

struct VectorDomain
  : proto::domain<proto::generator<VectorExpr>, VectorGrammar>
{};



template<typename Expr>
struct VectorExpr
  : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>
{
    explicit VectorExpr(Expr const &expr)
      : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>(expr)
    {}

typename proto::result_of::eval<Expr const, VectorSubscriptCtx const>::type
    operator []( std::size_t i ) const
    {
        VectorSubscriptCtx const ctx(i);
        return proto::eval(*this, ctx);
    }
};




class Vector {
private:
  int sz;
  double* data;

public:
  typedef double value_type;

  explicit Vector(int sz_ = 1, double iniVal = 0.0) :
    sz( sz_), data( new double[sz] ) {
    for (int i = 0; i < sz; i++) data[i] = iniVal;
  }
  Vector(const Vector& vec) :
    sz( vec.sz), data( new double[sz] ) {
    for (int i = 0; i < sz; i++) data[i] = vec.data[i];
  }

  size_t size() const {return sz; }

  ~Vector() {
    delete [] data;
  }

  double& operator[](int i) { return data[i]; }
  const double& operator[](int i) const { return data[i]; }
};



class Vector10: public Vector
{
public:
  Vector10() : Vector(10,0.0) {}
};




template<typename T>
struct IsVector
  : mpl::false_
{};


template<>
struct IsVector< Vector >
  : mpl::true_
{};



namespace VectorOps
{
    BOOST_PROTO_DEFINE_OPERATORS(IsVector, VectorDomain)

    typedef VectorSubscriptCtx const CVectorSubscriptCtx;

    template<typename Expr>
    Vector &assign(Vector &arr, Expr const &expr)
    {
        for(std::size_t i = 0; i < arr.size(); ++i)
        {
            arr[i] = proto::as_expr<VectorDomain>(expr)[i];
        }
        return arr;
    }
}



int main()
{
    using namespace VectorOps;

    Vector a,b,c,d;

    VectorOps::assign(d, a + b );
}


// ------------------------------------------------------------


There's already the derived class Vector10 defined. Now - using that one instead of Vector

int main()
{
    using namespace VectorOps;

    Vector10 a,b,c,d;

    VectorOps::assign(d, a + b );
}


I believe that the operators for Vector are correctly defined in the namespace VectorOps but the ADL doesn't kick in for the derived class.

Any idea how this can be fixed?

Thanks,
Frank




_______________________________________________
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto

Reply via email to