質問

私は私のコードが悪いのかを把握することができませんよ。ブーストのテンプレートは、私が夢中になっています!私はこのすべての外に頭や尾を作ることができないので、私はちょうど聞きしました。

これで間違っているのですか?

#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/spirit/include/qi.hpp>

void parsePathTest(const std::string &path)
{
    namespace lambda = boost::lambda;
    using namespace boost::spirit;

    const std::string permitted = "._\\-#@a-zA-Z0-9";
    const std::string physicalPermitted = permitted + "/\\\\";
    const std::string archivedPermitted = permitted + ":{}";

    std::string physical,archived;

    // avoids non-const reference to rvalue
    std::string::const_iterator begin = path.begin(),end = path.end();

    // splits a string like "some/nice-path/while_checking:permitted#symbols.bin"
    // as physical = "some/nice-path/while_checking"
    // and archived = "permitted#symbols.bin" (if this portion exists)
    // I could barely find out the type for this expression
    auto expr
        =   ( +char_(physicalPermitted) ) [lambda::var(physical) = lambda::_1]
            >> -(
                    ':'
                    >> (
                           +char_(archivedPermitted) [lambda::var(archived) = lambda::_1]
                       )
                )
        ;

    // the error occurs in a template instantiated from here
    qi::parse(begin,end,expr);

    std::cout << physical << '\n' << archived << '\n';
}

のエラーの数は莫大です。私は彼らの上にこれをコンパイルする手助けをしたい人は(ここで貼り付けることは非現実的である、私を信頼して)お勧めします。私は、最新のTDM-GCCのバージョン(GCC 4.4.1)を使用して、バージョン1.39.00を後押ししています。

ボーナスとして、私は他の二つのことをお願いしたいと思います:C ++ 0xの新static_assert機能は、この意味での後押しを助けるかどうか、そして、私が使用する必要がある場合、私は上に引用してきた実装は良いアイデアである、またはかどうかブーストの文字列アルゴリズムライブラリ。後者は、おそらくはるかに優れた性能を与えるでしょうか?

感謝します。

- 編集

以下の非常に最小限のサンプルは、上記のコードとまったく同じエラーで最初に失敗します。

#include <iostream>
#include <boost/spirit/include/qi.hpp>

int main()
{
    using namespace boost::spirit;

    std::string str = "sample";
    std::string::const_iterator begin(str.begin()), end(str.end());

    auto expr
        =   ( +char_("a-zA-Z") )
        ;

    // the error occurs in a template instantiated from here
    if (qi::parse(begin,end,expr))
    {
        std::cout << "[+] Parsed!\n";
    }
    else
    {
        std::cout << "[-] Parsing failed.\n";
    }

    return 0;
}

- 編集2

私はまだそれがブーストの私の古いバージョン(1.39)で動作しなかった理由を知っているが、1.42を後押しするためにアップグレードしても問題は解決しません。次のコードはコンパイルされ、ブースト1.42と完璧に動作します:

#include <iostream>
#include <boost/spirit/include/qi.hpp>

int main()
{
    using namespace boost::spirit;

    std::string str = "sample";
    std::string::const_iterator begin(str.begin()), end(str.end());

    auto expr
        =   ( +qi::char_("a-zA-Z") ) // notice this line; char_ is not part of 
                                     // boost::spirit anymore (or maybe I didn't 
                                     // include the right headers, but, regardless, 
                                     // khaiser said I should use qi::char_, so here 
                                     // it goes)
        ;

    // the error occurs in a template instantiated from here
    if (qi::parse(begin,end,expr))
    {
        std::cout << "[+] Parsed!\n";
    }
    else
    {
        std::cout << "[-] Parsing failed.\n";
    }

    return 0;
}

のヒントのおかげで、hkaiserます。

役に立ちましたか?

解決

いくつかの発言:a)のブーストV1.39とV1.40と一緒に配布スピリットV2のベータ版を使用しないでください。それはの多くが含まれているとして、代わりに(ブーストV1.41をリリースしたように)少なくともスピリットV2.1を使用してください。のバグ修正とパフォーマンスの向上のは(両方とも、時間と実行時のパフォーマンスをコンパイル)。あなたはブーストのバージョンを切り替えることができない場合は、<のhref = "http://boost-spirit.com/home/articles/spirit2-1-release/using-spirit-v2-1-with-older-versions-ofを読みますここを続行する方法について-boost-事前v1-41 /」のrel = "noreferrer">。 B)::ブーストを使用しないようにしてくださいラムダまたは後押し::スピリットV2.x.とのバインドをはい、私は知っている、ドキュメントはそれが動作すると言うが、あなたは何をやっている知っている必要があります。代わりにブースト::フェニックス式を使用します。スピリットは、簡単にセマンティックアクションを書くことになりフェニックス、「について知っています」。あなたはフェニックスを使用している場合は、あなたのコードは次のようになります。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

std::string physical, archived;  
auto expr 
    =   ( +char_(physicalPermitted) ) [phoenix::ref(physical) = qi::_1] 
    >> -( 
            ':' 
            >> ( +char_(archivedPermitted) )[phoenix::ref(archived) = qi::_1] 
        ) 
    ; 

しかし、あなたは聖霊の組み込み属性の伝播ルールを活用場合は、あなたの全体的なパーサがさらに簡単になります。

std::string physical;
boost::optional<std::string> archived;  

qi::parse(begin, end, 
    +qi::char_(physicalPermitted) >> -(':' >> +qi::char_(archivedPermitted)),
    physical, archived);

すなわち。すべてのセマンティックアクションを持っている必要はありません。あなたが扱う属性の詳細情報が必要な場合は、スピリットのウェブサイト上の属性の魔法についての連載を参照してください。

編集ます:

あなたのstatic_assert質問について:可能な限り早期にコンパイルエラーをトリガするために使用することができるようはいstatic_assert、エラーメッセージを向上させることができます。実際には、聖霊が広く、すでにこの技術を使用しています。しかし、すべてのケースで、これらの巨大なエラーメッセージを得ることからユーザーを保護することはできませんが、のみユーザー・エラーのためにプログラマが期待していませんでした。 (残念ながら新しいC ++標準にそれをしなかった)だけの概念は、一般的なエラーメッセージのtehのサイズを小さくするために使用されている可能性があります。

あなたのブーストの文字列アルゴリズムの質問について:確かにそれはあなたのように単純なタスクのために、このライブラリを利用することが可能です。あなたも(「:」あなたが必要とするすべてはで入力文字列を分割する場合)Boost.Tokenizerを使用したほうが良いかもしれません。御霊のパフォーマンスは、文字列アルゴリズムの対応するパフォーマンスに匹敵する必要がありますが、これは確かにあなたが書いされるコードに依存します。あなたが使用した文字列のアルゴリズムは、入力された文字列データの上で1つのパスが必要になると仮定した場合(それが同様に1つのパスをやっているように)、そして聖霊は速くなりません。

ブースト文字列アルゴリズムもブーストどちらトークナイザは、あなたにマッチした文字の検証を与えることができます。あなたの精神の文法を使用すると、文字クラスに指定された文字のみにマッチします。あなたはこのマッチング/検証が必要であれば、あなたは霊のいずれかを使用するか、正規表現を後押しする必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top