Как я могу использовать оператор "new" в семантическом действии boost::xpressive?

Кажется, что boost:: xpressive не предоставляет лениво оцененную версию new оператор, поэтому это семантическое действие не будет компилироваться:

using namespace boost::xpressive ;
std::vector<int*> vec ;

// Match any integer and capture into s1.
// Then use a semantic action to push it onto vec.
sregex num = (s1= +digit)[ ref(vec)->*push_back( new as<int>(s1) ) ] ;

Существует ли конструкция для использования оператора new в семантических действиях? Например, boost::phoenix предоставляет new_ функция для лямбд. Предоставляет ли xpressive нечто подобное для семантических действий?

1 ответ

Это лучшее, что я придумал до сих пор. Этот код определяет функцию, которая позволяет использовать синтаксис new_<T>::with(...) как семантическое действие, эквивалентное new T(...), Эта функция смоделирована после ленивого примера функции в руководстве пользователя boost xpressive. (Приведенный ниже фрагмент поддерживает только конструкторы с максимум 2 параметрами, но добавление еще зависит от копирования / вставки.)

using namespace boost::xpressive ;

template <typename _ObjectType>
struct new_impl
{
    typedef _ObjectType* result_type;

    _ObjectType* operator()() const
    {
        return new _ObjectType() ;
    }

    template<typename _T0>
    _ObjectType* operator()(_T0 const &a0) const
    {
        return new _ObjectType( a0 ) ;
    }

    template<typename _T0, typename _T1>
    _ObjectType* operator()(_T0 const &a0, _T1 const &a1) const
    {
        return new _ObjectType( a0, a1 ) ;
    }
};

template <typename _ObjectType>
struct new_
{
    static const typename function<new_impl<_ObjectType> >::type with ;
};
template <typename _ObjectType>
const typename function<new_impl<_ObjectType> >::type new_<_ObjectType>::with = {{}};

И вот оно в действии:

int main()
{
    std::vector<int*> vec ;

    // Matches an integer, with a semantic action to push it onto vec
    sregex num = (s1= +digit)
                 [ ref(vec)->*push_back( new_<int>::with( as<int>(s1) ) ) ] ;

    // Space-delimited list of nums
    sregex num_list = num >> *(' ' >> num) ;

    std::string str = "8 9 10 11" ;
    if ( regex_match( str, num_list ) )
    {
        std::cout << "Found an int list: " ;
        BOOST_FOREACH( int* p, vec )
        {
            std::cout << *p << ' ' ;
        }
    }
    else
    {
        std::cout << "Didn't find an int list." ;
    }

    return 0 ;
}

Выход:

Found an int list: 8 9 10 11

Чтобы улучшить общность кода выше, может быть лучше изменить типы параметров для использования boost::add_reference<> а также boost::add_const<>, Но ты получил идею.

Другие вопросы по тегам