Search code examples
c++boost-spiritboost-spirit-qi

How do I forward declare a boost::spirit rule?


Here's a very simple boost::spirit example demonstrating an issue I'm running into - when I compile it, I get 'parsers::parseTest': redefinition; multiple initialization - how do I forward declare a rule? Using 2.5.2 if it matters.

#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted/adt/adapt_adt.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <string>

struct test
{
    int a;
    int b;
};

BOOST_FUSION_ADAPT_STRUCT(test, a,b)


namespace parsers
{
    typedef std::string::const_iterator it;
    using namespace boost::spirit::qi;
    const rule<it, test()> parseTest;
}

namespace parsers
{
    typedef std::string::const_iterator it;
    using namespace boost::spirit::qi;
    const rule<it, test()> parseTest = int_ >> ',' >> int_;
}

Solution

  • Constant declaration const rule<it, test()> parseTest; is also its definition, which, in this code, uses the default constructor to initialize it. Just omit that line.

    Alternatively, if you want to provide parseTest definition with the initializer in another source file, you must declare that const as extern because const at global and namespace scope implies internal linkage (static).

    // .h
    namespace parsers {
        extern const rule<it, test()> parseTest;
    }
    
    // .cc
    const rule<it, test()> parsers::parseTest = int_ >> ',' >> int_;