0

したがって、私は次の精神カルマ ルール本体を持っています。

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た(はい、それは間違っています。単なる実験でした)。

質問:

ポイントがゼロのときにルール本体の評価を防ぐために、スピリット eps コンストラクトを使用してプレースホルダーでポインター テストを実行するにはどうすればよいですか?

すべての「C++ 関数型プログラミング ライブラリの使用法」の質問と同様に、私は答えがぼんやりした感じになることを期待しています。

答え

Ildjam のポイントは、私の質問に直接答えます。私の問題には2つの問題がありました。上記の間接的な問題があります。そして、それは PEG の条件に関係しています。私が表現しようとしていることは、次のように書く必要があります。

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

文法の条件部分を表現するために、セマンティック アクション ボディ ([] ブロックで指定) を使用していました。不思議なことに、以前に条件付き PEG 文法を書いたことがありますが、間違いを犯したため、2 番目のクラスの問題が発生しました。

したがって、eps(_r1) はそのトリックを行います。2 番目のタイプのコンパイルの問題は、質問とは無関係です。

4

2 に答える 2

3

これは、C++03 の C++ 型システムの根本的な問題です。0 は特別であり、タイプ, , が使用できない多くの場所で使用できます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;
    }
};
于 2011-06-01T16:52:30.657 に答える
2

私のコメントで提案されているように、暗黙的なポインタから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;
}

したがって、この方法で暗黙的な変換を使用しようとしているときに発生する問題が何であれ、それはコードに固有のものでなければなりません。つまり、有用なフィードバックを得るには、より多くのコードを表示する必要があります。

于 2011-06-01T17:14:15.957 に答える