Функциональное программирование на языке c ++ (boost :: phoenix && boost :: spirit) тестирование нулевых ptrs в заполнителях указателей - PullRequest
0 голосов
/ 01 июня 2011

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

base_rule = 
    eps(_r1 != 0) [ // _r1 is a pointer_typed placeholder
        eps
    ]
;

, что приводит к довольно длинному сообщению об ошибке от g ++, которое (полезно) заканчивается на:

/opt/dev_64_swat/Boost/include/boost/spirit/home/phoenix/operator/comparison.hpp
:37:5: error: ISO C++ forbids comparison between pointer and integer 
[-fpermissive]

Это действительно c ++:

struct zebra{};

int main()
{
  zebra * x;
  if( x == 0);  
}

Я подумал попробовать boost::phoenix::static_cast_<_r1_type *>(0), а также преобразовать _r1_type в целое число (да, это НЕПРАВИЛЬНО, это был просто эксперимент).

Вопрос:

Как я могу использовать конструкцию Spirit eps для выполнения теста указателя на заполнитель, чтобы предотвратить оценку тела правила, когда точка равна нулю?

Как и во всех вопросах «Использование функциональной библиотеки C ++», я ожидаю, что ответ заставит меня чувствовать себя бестолковым.

Ответ

Точка Ильджама прямо отвечает на мой вопрос. Были две проблемы с моей проблемой; выше есть косвенная проблема. И это связано с условностями в PEG. То, что я пытаюсь выразить, должно быть написано так:

rule = ( eps(_r) << ( /* grammar for when pointer is not null */ ) ) 
    | eps // otherwise dont do anything.
;

Я использовал тело семантического действия (указанное в блоке []), чтобы выразить условную часть грамматики. Как ни странно, хотя раньше я писал условные грамматики PEG, я просто допустил ошибку, которая привела ко второму классу проблем.

Итак, eps (_r1) делает свое дело. Второй тип проблемы компиляции не имеет отношения к вопросу.

Ответы [ 2 ]

3 голосов
/ 01 июня 2011

Это фундаментальная проблема с системой типов C ++ в C ++ 03.Значение 0 является специальным и может использоваться во многих местах, где оно type , int не может.Эта проблема легко демонстрируется и вызывает множество проблем при объединении шаблонов и указателей.

void f(int i) {
    void* ptr = ...;
    if (ptr == i) { // MALFORMED
    }
}

f(0); // But I'm trying to compare with 0, which is legit!

template<typename T, typename Y> T construct_from(const Y& y) {
    return T(y);
}
construct_from<void*>(0); // ERROR, cannot construct ptr from int.

Самое простое решение - написать быструю версию nullptr, которую можно найти в C ++ 0x.

struct nullptr_t {
    template<typename T> operator T*() const {
        return 0;
    }
};
2 голосов
/ 01 июня 2011

Использование неявного преобразования указатель в bool, как предлагается в моем комментарии, работает для меня из коробки с Boost 1.46.1. Следующее является минимальным репро, где parse успешен, если (и только если) p != 0 && input == "not null" или p == 0 && input == "null":

#include <string>
#include <ios>
#include <ostream>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace spirit = boost::spirit;
namespace qi = spirit::qi;

struct test_grammar : qi::grammar<std::string::const_iterator, void(int*)>
{
    test_grammar() : base_type(start_)
    {
        start_
            =   (   spirit::eps(spirit::_r1)
                    >> "not null"
                |   spirit::eps(!spirit::_r1)
                    >> "null"
                )
                >> spirit::eoi
            ;
    }

private:
    qi::rule<base_type::iterator_type, base_type::sig_type> start_;
};
test_grammar const test;

int main()
{
    int i = 42;
    int* p = &i;                          // alternatively, = 0;
    std::string const input = "not null"; // alternatively, = "null";

    std::string::const_iterator first = input.begin();
    std::cout
        << std::boolalpha
        << "parse succeeded: "
        << qi::parse(first, input.end(), test(p))
        << std::endl;
}

Итак, какие бы проблемы у вас ни возникали при попытке использовать неявное преобразование таким образом, это должно быть специфично для вашего кода; то есть вам нужно будет показать больше своего кода, чтобы получить полезную обратную связь.

...