2011-06-25 5 views
10

Estoy tratando de hacer una gramática en Boost.Proto que coincida con un tipo de vector, pero cuando le doy un terminal de ese tipo, no coincide con la gramática. La definición de tipo se parece a esto:Coincidencia de una gramática Boost.Proto con un tipo

template <typename T, unsigned D> 
struct vector 
{ 
    typedef T scalar; 
    enum { size = D }; 

    scalar& operator[](unsigned i) 
    { 
     return m_components[i]; 
    } 

    scalar const& operator[](unsigned i) const 
    { 
     return m_components[i]; 
    } 

private: 
    scalar m_components[size]; 
}; 

La gramática que estoy tratando de llegar a coincidir ve algo como esto:

namespace proto = boost::proto; 
using proto::_; 
using proto::N; 

struct test: 
    proto::terminal<vector<_, N> > 
{}; 

la comparación falla:

int main() 
{ 
    BOOST_MPL_ASSERT((proto::matches<proto::terminal<vector<float, 2> >::type, test>)); 
} 

Cómo hacer yo hacer una gramática que coincida con un tipo específico?

EDIT:

Parece que proto :: _ y proto :: N no está siendo utilizado como un comodín en los tipos personalizados. El código se compila con esta gramática (el matches afirmación pasa):

struct test: 
    proto::terminal<vector<float, 2> > 
{}; 

Pero no funciona cuando uno de los comodines se encuentran en el tipo:

struct test: 
    proto::terminal<vector<float, N> > 
{}; 

O:

struct test: 
    proto::terminal<vector<_, 2> > 
{}; 

Entonces, si no puedo usar mis propios tipos de comodines, ¿cómo puedo probar si la expresión es un terminal que contiene un vector?

Respuesta

6

Boost.Proto no funciona con los parámetros de plantilla no tipo . Si puede, cambiar el tipo de vector para usar envolturas de tipo integral, así:

template <typename T, typename D> 
struct vector 
{ 
    typedef T scalar; 
    enum { size = D::value }; 

    scalar& operator[](unsigned i) 
    { 
     return m_components[i]; 
    } 

    scalar const& operator[](unsigned i) const 
    { 
     return m_components[i]; 
    } 

private: 
    scalar m_components[size]; 
}; 

Entonces usted debe ser capaz de igualar la siguiente manera:

int main() 
{ 
    BOOST_MPL_ASSERT((proto::matches< 
     proto::terminal<vector<float, mpl::int_<2> > >::type, 
     proto::terminal<vector<_, _> > 
    >)); 
} 

Espero que ayude!

7

Para comparar el tipo dentro de un terminal con un tipo, puede usar rasgos de tipo. Tengo algunas estructuras rasgos establecidos que dan como resultado true si el tipo dado es un vector:

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


template <typename T, unsigned Size> 
struct is_vector <dev::math::vector <T, Size> >: 
    boost::mpl::true_ 
{}; 

y luego se puede poner esto en su gramática:

proto::and_< 
    proto::terminal<_>, 
    proto::if_<is_vector<proto::_value>()> 
> 

He intentado este enfoque antes , pero la razón por la que no funcionó fue porque yo declaré transmita vector < ...> en el espacio de nombres mal en la cabecera de las estructuras rasgos estaban.

+0

Intentando lo mismo en una clase de matriz multi-D personalizada. Me pregunto si es mejor adaptar proto a mi clase, o mi clase a proto. Intento seguir el primer camino, ya que no quiero estropear muchas cosas que ya funcionan, pero no estoy seguro – Giuliano

Cuestiones relacionadas