Соответствие грамматике Boost.Proto типу - PullRequest
10 голосов
/ 25 июня 2011

Я пытаюсь создать грамматику в Boost.Proto, которая соответствует векторному типу, но когда я даю ему терминал этого типа, он не соответствует грамматике. Определение типа выглядит так:

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];
};

Грамматика, которую я пытаюсь найти, выглядит примерно так:

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

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

Матч не удался:

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

Как создать грамматику, соответствующую определенному типу?

EDIT:

Похоже, что proto :: _ и proto :: N не используются в качестве подстановочных знаков в пользовательских типах. Код компилируется с этой грамматикой (проходит утверждение matches):

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

Но не работает, когда один из подстановочных знаков относится к типу:

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

Или:

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

Так что, если я не могу использовать подстановочные знаки своих собственных типов, как я могу проверить, является ли выражение терминалом, содержащим вектор?

Ответы [ 2 ]

7 голосов
/ 26 июня 2011

Чтобы сравнить тип в терминале с типом, вы можете использовать черты типа. У меня есть некоторые настроенные структуры черт, которые оценивают в true, если данный тип является вектором:

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_
{};

И тогда вы можете поместить это в свою грамматику:

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

Я пробовал этот подход раньше, но причина, по которой он не сработал, заключалась в том, что я перенаправил объявленный вектор <...> в неправильное пространство имен в заголовке, в котором находились структуры черт.

6 голосов
/ 18 июля 2011

Boost.Proto не работает с нетиповыми параметрами шаблона. Если вы можете, измените ваш векторный тип, чтобы использовать обертки целочисленного типа, например:

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];
};

Тогда вы должны быть в состоянии соответствовать следующим образом:

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

Надеюсь, это поможет!

...